|
|
1.1 root 1: #undef CHECK_WORD_IMMEDIATES /* bug #26863 */
2:
3: /* m68k.c All the m68020 specific stuff in one convenient, huge,
4: slow to compile, easy to find file.
5: Copyright (C) 1987 Free Software Foundation, Inc.
6:
7: This file is part of GAS, the GNU Assembler.
8:
9: GAS is free software; you can redistribute it and/or modify
10: it under the terms of the GNU General Public License as published by
11: the Free Software Foundation; either version 1, or (at your option)
12: any later version.
13:
14: GAS is distributed in the hope that it will be useful,
15: but WITHOUT ANY WARRANTY; without even the implied warranty of
16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: GNU General Public License for more details.
18:
19: You should have received a copy of the GNU General Public License
20: along with GAS; see the file COPYING. If not, write to
21: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22:
23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <ctype.h>
27: #include "m68k-opcode.h"
28: #include "as.h"
29: #include "obstack.h"
30: #include "struc-symbol.h"
31: #include "flonum.h"
32: #include "expr.h"
33: #include "hash.h"
34: #include "frags.h"
35: #include "fixes.h"
36: #include "read.h"
37: #include "md.h"
38: #ifndef NeXT
39: #include "m68k.h"
40: #endif /* NeXT */
41: #include "xmalloc.h"
42: #include "sections.h"
43: #include "messages.h"
44: #include "atof-ieee.h"
45: #include "input-scrub.h"
46: #include "symbols.h"
47:
48: /*
49: * These are the default cputype and cpusubtype for the m68k architecture.
50: */
51: const cpu_type_t md_cputype = CPU_TYPE_MC680x0;
52: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC680x0_ALL;
53:
54: /* This is the byte sex for the m68k architecture */
55: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
56:
57: /*
58: * This array holds the chars that always start a comment. If the
59: * pre-processor is disabled, these aren't very useful.
60: */
61: const char md_comment_chars[] = "|";
62:
63: /*
64: * This array holds the chars that only start a comment at the beginning of
65: * a line. If the line seems to have the form '# 123 filename'
66: * .line and .file directives will appear in the pre-processed output.
67: *
68: * Note that input_file.c hand checks for '#' at the beginning of the
69: * first line of the input file. This is because the compiler outputs
70: * #NO_APP at the beginning of its output.
71: *
72: * Also note that a '/' followed by a '*' will always start a comment.
73: */
74: const char md_line_comment_chars[] = "#";
75:
76: /* Chars that can be used to separate mant from exp in floating point nums. */
77: const char md_EXP_CHARS[] = "eE";
78:
79: /*
80: * Chars that mean this number is a floating point constant.
81: * As in 0f12.456
82: * or 0d1.2345e12
83: *
84: * Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
85: * changed in read.c . Ideally it shouldn't have to know about it at all,
86: * but nothing is ideal around here.
87: */
88: const char md_FLT_CHARS[] = "rRsSfFdDxXeEpP";
89:
90: /* Its an arbitrary name: This means I don't approve of it */
91: /* See flames below */
92: static struct obstack robyn;
93:
94: /*
95: * These macros are used to encode a mode for the rlx_more field of the struct
96: * relax_typeS in the array md_relax_table below. The array is indexed by a
97: * TAB(x,y) value where x is one of BRANCH, FBRANCH, ... and y is BYTE, SHORT,
98: * ... Thus the array md_relax_table below is declared to match this use of
99: * indexes. The macro TABTYPE(xy) take the value and returns one of BRANCH,
100: * FBRANCH, ...
101: */
102: #define TAB(x,y) (((x)<<2)+(y))
103: #define TABTYPE(xy) ((xy) >> 2)
104:
105: #define BRANCH 1
106: #define FBRANCH 2
107: #define PCREL 3
108: #define BCC68000 4
109: #define DBCC 5
110:
111: #define BYTE 0
112: #define SHORT 1
113: #define LONG 2
114: #define SZ_UNDEF 3
115:
116: /*
117: * BCC68000 is for patching in an extra jmp instruction for long offsets
118: * on the 68000. The 68000 doesn't support long branches with branchs.
119: */
120:
121: /*
122: * Note that calls to frag_var need to specify the maximum expansion needed.
123: * This is currently 10 bytes for DBCC.
124: */
125:
126: /*
127: * This table desribes how you change sizes for the various types of variable
128: * size expressions. This version only supports two kinds.
129: * The fields are:
130: * How far Forward this mode will reach:
131: * How far Backward this mode will reach:
132: * How many bytes this mode will add to the size of the frag
133: * Which mode to go to if the offset won't fit in this one
134: */
135: const
136: relax_typeS
137: md_relax_table[] = {
138: { 1, 1, 0, 0 }, /* First entries aren't used */
139: { 1, 1, 0, 0 }, /* For no good reason except */
140: { 1, 1, 0, 0 }, /* that the VAX doesn't either */
141: { 1, 1, 0, 0 },
142:
143: { (127), (-128), 0, TAB(BRANCH,SHORT)},
144: { (32767), (-32768), 2, TAB(BRANCH,LONG) },
145: { 0, 0, 4, 0 },
146: { 1, 1, 0, 0 },
147:
148: { 1, 1, 0, 0 }, /* FBRANCH doesn't come BYTE */
149: { (32767), (-32768), 2, TAB(FBRANCH,LONG)},
150: { 0, 0, 4, 0 },
151: { 1, 1, 0, 0 },
152:
153: { 1, 1, 0, 0 }, /* PCREL doesn't come BYTE */
154: { (32767), (-32768), 2, TAB(PCREL,LONG)},
155: { 0, 0, 4, 0 },
156: { 1, 1, 0, 0 },
157:
158: { (127), (-128), 0, TAB(BCC68000,SHORT)},
159: { (32767), (-32768), 2, TAB(BCC68000,LONG) },
160: { 0, 0, 6, 0 }, /* jmp long space */
161: { 1, 1, 0, 0 },
162:
163: { 1, 1, 0, 0 }, /* DBCC doesn't come BYTE */
164: { (32767), (-32768), 2, TAB(DBCC,LONG) },
165: { 0, 0, 10, 0 }, /* bra/jmp long space */
166: { 1, 1, 0, 0 },
167:
168: };
169:
170: static void s_even(
171: int value);
172: static void s_proc(
173: int value);
174:
175: /*
176: * These are the machine dependent pseudo-ops. These are included so
177: * the assembler can work on the output from the SUN C compiler, which
178: * generates these.
179: */
180:
181: /* This table describes all the machine specific pseudo-ops the assembler
182: * has to support. The fields are:
183: * pseudo-op name without dot
184: * function to call to execute this pseudo-op
185: * Integer arg to pass to the function
186: */
187: const pseudo_typeS md_pseudo_table[] = {
188: { "float", float_cons, 'f' },
189: { "int", cons, 4 },
190: { "word", cons, 2 },
191: { "quad", big_cons, 8 },
192: { "octa", big_cons, 16 },
193: { "even", s_even, 0 },
194: { "skip", s_space, 0 },
195: { "proc", s_proc, 0 },
196: { 0, 0, 0 }
197: };
198:
199: #define issbyte(x) ((x)>=-128 && (x)<=127)
200: #define isubyte(x) ((x)>=0 && (x)<=255)
201: #define issword(x) ((x)>=-32768 && (x)<=32767)
202: #define isuword(x) ((x)>=0 && (x)<=65535)
203:
204: #define isbyte(x) ((x)>=-128 && (x)<=255)
205: #define isword(x) ((x)>=-32768 && (x)<=65535)
206: #define islong(x) (1)
207:
208: /* Operands we can parse: (And associated modes)
209:
210: numb: 8 bit num
211: numw: 16 bit num
212: numl: 32 bit num
213: dreg: data reg 0-7
214: reg: address or data register
215: areg: address register
216: apc: address register, PC, ZPC or empty string
217: num: 16 or 32 bit num
218: num2: like num
219: sz: w or l if omitted, l assumed
220: scale: 1 2 4 or 8 if omitted, 1 assumed
221:
222: 7.4 IMMED #num --> NUM
223: 0.? DREG dreg --> dreg
224: 1.? AREG areg --> areg
225: 2.? AINDR areg@ --> *(areg)
226: 3.? AINC areg@+ --> *(areg++)
227: 4.? ADEC areg@- --> *(--areg)
228: 5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here
229: 6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale)
230: 6.? AINDX apc@(reg:sz:scale) --> same, with num=0
231: 6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale)
232: 6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0
233: 6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg)
234: 6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2)
235: 6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0
236: 7.0 ABSL num:sz --> *(num)
237: num --> *(num) (sz L assumed)
238: *** MSCR otherreg --> Magic
239: With -l option
240: 5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still
241:
242: examples:
243: #foo #0x35 #12
244: d2
245: a4
246: a3@
247: a5@+
248: a6@-
249: a2@(12) pc@(14)
250: a1@(5,d2:w:1) @(45,d6:l:4)
251: pc@(a2) @(d4)
252: etc . . .
253:
254:
255: #name@(numw) -->turn into PC rel mode
256: apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale)
257:
258: */
259:
260: #define IMMED 1
261: #define DREG 2
262: #define AREG 3
263: #define AINDR 4
264: #define ADEC 5
265: #define AINC 6
266: #define AOFF 7
267: #define AINDX 8
268: #define APODX 9
269: #define AMIND 10
270: #define APRDX 11
271: #define ABSL 12
272: #define MSCR 13
273: #define REGLST 14
274:
275: #define FAIL 0
276: #define OK 1
277:
278: /* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7==data reg,
279: 8-15==addr reg for operands that take both types */
280: #define DATA 1 /* 1- 8 == data registers 0-7 */
281: #define ADDR (DATA+8) /* 9-16 == address regs 0-7 */
282: #define FPREG (ADDR+8) /* 17-24 Eight FP registers */
283: #define COPNUM (FPREG+8) /* 25-32 Co-processor #1-#8 */
284: #undef PC
285: #define PC (COPNUM+8) /* 33 Program counter */
286: #define ZPC (PC+1) /* 34 Hack for Program space, but 0 addressing */
287: #define SR (ZPC+1) /* 35 Status Reg */
288: #define CCR (SR+1) /* 36 Condition code Reg */
289:
290: #define FPI (CCR+1) /* 37 floating-point instruction register */
291: #define FPS (FPI+1) /* 38 floating-point status register */
292: #define FPC (FPS+1) /* 39 floating-point condition register */
293:
294: /* These have to be in order for the movec instruction to work. */
295: /* The comment above should read: All the registers that can be in a movec
296: instruction must be bounded by USP and MSP (or SRP if BUILTIN_MMUS is
297: defined) for the 'J' kind of operand to be checked correctly in m68_ip() */
298: #define USP (FPC+1) /* 40 User Stack Pointer */
299: #define ISP (USP+1) /* 41 Interrupt stack pointer */
300: #define SFC (ISP+1) /* 42 Source function control code register */
301: #define DFC (SFC+1) /* 43 Destination function code register */
302: #define CACR (DFC+1) /* 44 Cashe control register */
303: #define VBR (CACR+1) /* 45 wector base register */
304: #define CAAR (VBR+1) /* 46 Cashe address register */
305: #define MSP (CAAR+1) /* 47 Master stack pointer */
306:
307: #ifdef BUILTIN_MMUS
308: /* mc68040 mmu registers, can be used in a movec instruction */
309: #define ITT0 (MSP+1) /* 48 instruction transparent translation register 0 */
310: #define ITT1 (ITT0+1) /* 49 instruction transparent translation register 1 */
311: #define DTT0 (ITT1+1) /* 50 data transparent translation register 0 */
312: #define DTT1 (DTT0+1) /* 51 data transparent translation register 1 */
313: #define URP (DTT1+1) /* 53 user root pointer */
314:
315: /* mc68030 and mc68040 mmu registers, can be used in a movec instruction */
316: #define MMUSR (URP+1) /* 52 MMU status register */
317: #define TC (MMUSR+1)/* 54 MMU translation control register */
318: #define SRP (TC+1) /* 55 supervisor root pointer */
319:
320: /* mc68030 mmu registers, can't be used in a movec instruction (but rather in a
321: pmove instruction) */
322: #define CRP (SRP+1) /* 56 cpu root pointer */
323: #define TT0 (CRP+1) /* 57 transparent translation register 0 */
324: #define TT1 (TT0+1) /* 58 transparent translation register 0 */
325:
326: /* mc68040 operands to cache instructions */
327: #define IC (TT1+1) /* 59 instruction cache */
328: #define DC (IC+1) /* 60 data cache */
329: #define BC (DC+1) /* 61 both instruction and data caches */
330: #endif /* BUILTIN_MMUS */
331:
332: #ifdef m68851
333: /*
334: * these defines should be in m68k.c but
335: * i put them here to keep all the m68851 stuff
336: * together -rab
337: * JF--Make sure these #s don't clash with the ones in m68k.c
338: * That would be BAD.
339: */
340: #define TC (MSP+1) /* 48 */
341: #define DRP (TC+1) /* 49 */
342: #define SRP (DRP+1) /* 50 */
343: #define CRP (SRP+1) /* 51 */
344: #define CAL (CRP+1) /* 52 */
345: #define VAL (CAL+1) /* 53 */
346: #define SCC (VAL+1) /* 54 */
347: #define AC (SCC+1) /* 55 */
348: #define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */
349: #define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */
350: #define PSR (BAC+8) /* 72 */
351: #define PCSR (PSR+1) /* 73 */
352: #endif m68851
353:
354:
355: /* Note that COPNUM==processor #1 -- COPNUM+7==#8, which stores as 000 */
356: /* I think. . . */
357:
358: #undef SP
359: #define SP ADDR+7
360:
361: /* JF these tables here are for speed at the expense of size */
362: /* You can replace them with the #if 0 versions if you really
363: need space and don't mind it running a bit slower */
364:
365: static char mklower_table[256];
366: #define mklower(c) (mklower_table[(unsigned char)(c)])
367: static char notend_table[256];
368: static char alt_notend_table[256];
369: #define notend(s) ( !(notend_table[(unsigned char)(*s)] || (*s==':' &&\
370: alt_notend_table[(unsigned char)(s[1])])))
371:
372: #if 0
373: #define mklower(c) (isupper(c) ? tolower(c) : c)
374: #endif
375:
376:
377: struct m68k_exp {
378: char *e_beg;
379: char *e_end;
380: expressionS e_exp;
381: short e_siz; /* 0== default 1==short/byte 2==word 3==long */
382: };
383:
384: /* Internal form of an operand. */
385: struct m68k_op {
386: char *error; /* Couldn't parse it */
387: int mode; /* What mode this instruction is in. */
388: unsigned long int reg; /* Base register */
389: struct m68k_exp *con1;
390: int ireg; /* Index register */
391: int isiz; /* 0==unspec 1==byte(?) 2==short 3==long */
392: int imul; /* Multipy ireg by this (1,2,4,or 8) */
393: struct m68k_exp *con2;
394: };
395:
396: /* internal form of a 68020 instruction */
397: struct m68_it {
398: char *error;
399: char *args; /* list of opcode info */
400: int numargs;
401:
402: #ifdef NeXT
403: char *cpus;
404: #endif /* NeXT */
405: int numo; /* Number of shorts in opcode */
406: short opcode[11];
407:
408: struct m68k_op operands[6];
409:
410: int nexp; /* number of exprs in use */
411: struct m68k_exp exprs[4];
412:
413: int nfrag; /* Number of frags we have to produce */
414: struct {
415: int fragoff; /* Where in the current opcode[] the frag ends */
416: symbolS *fadd;
417: long int foff;
418: int fragty;
419: } fragb[4];
420:
421: int nrel; /* Num of reloc strucs in use */
422: struct {
423: int n;
424: symbolS *add,
425: *sub;
426: long int off;
427: char wid;
428: char pcrel;
429: } reloc[5]; /* Five is enough??? */
430: };
431:
432: static struct m68_it the_ins; /* the instruction being assembled */
433:
434:
435: /* Macros for adding things to the m68_it struct */
436:
437: #define addword(w) the_ins.opcode[the_ins.numo++]=(w)
438:
439: /* Like addword, but goes BEFORE general operands */
440: #define insop(w) {int z;\
441: for(z=the_ins.numo;z>opcode->m_codenum;--z)\
442: the_ins.opcode[z]=the_ins.opcode[z-1];\
443: for(z=0;z<the_ins.nrel;z++)\
444: the_ins.reloc[z].n+=2;\
445: the_ins.opcode[opcode->m_codenum]=(w);\
446: the_ins.numo++;\
447: }
448:
449:
450: #define add_exp(beg,end) (\
451: the_ins.exprs[the_ins.nexp].e_beg=(beg),\
452: the_ins.exprs[the_ins.nexp].e_end=(end),\
453: &the_ins.exprs[the_ins.nexp++]\
454: )
455:
456:
457: /* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch*/
458: #define add_fix(width,exp,pc_rel) {\
459: the_ins.reloc[the_ins.nrel].n= ((width)=='B') ? (the_ins.numo*2-1) : \
460: (((width)=='b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2));\
461: the_ins.reloc[the_ins.nrel].add=adds((exp));\
462: the_ins.reloc[the_ins.nrel].sub=subs((exp));\
463: the_ins.reloc[the_ins.nrel].off=offs((exp));\
464: the_ins.reloc[the_ins.nrel].wid=(width);\
465: the_ins.reloc[the_ins.nrel++].pcrel=(pc_rel);\
466: }
467:
468: #define add_frag(add,off,type) {\
469: the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\
470: the_ins.fragb[the_ins.nfrag].fadd=(add);\
471: the_ins.fragb[the_ins.nfrag].foff=(off);\
472: the_ins.fragb[the_ins.nfrag++].fragty=(type);\
473: }
474:
475: #define isvar(exp) ((exp) && (adds(exp) || subs(exp)))
476:
477: #define seg(exp) ((exp)->e_exp.X_seg)
478: #define adds(exp) ((exp)->e_exp.X_add_symbol)
479: #define subs(exp) ((exp)->e_exp.X_subtract_symbol)
480: #define offs(exp) ((exp)->e_exp.X_add_number)
481:
482:
483: struct m68_incant {
484: char *m_operands;
485: unsigned long m_opcode;
486: short m_opnum;
487: short m_codenum;
488: #ifdef NeXT
489: char *m_cpus;
490: #endif /* NeXT */
491: struct m68_incant *m_next;
492: };
493:
494: #define getone(x) ((((x)->m_opcode)>>16)&0xffff)
495: #define gettwo(x) (((x)->m_opcode)&0xffff)
496:
497: /*
498: * Declarations static functions in this file.
499: */
500: static int m68k_reg_parse(
501: char **ccp);
502: static int m68k_ip_op(
503: char *str,
504: struct m68k_op *opP);
505: static int try_index(
506: char **s,
507: struct m68k_op *opP);
508: static void m68_ip(
509: char *instring);
510: static int get_regs(
511: int i,
512: struct m68k_op *opP,
513: char *str);
514: static int reverse_16_bits(
515: int in);
516: static int reverse_8_bits(
517: int in);
518: static void install_operand(
519: int mode,
520: int val);
521: static void install_gen_operand(
522: int mode,
523: int val);
524: static char *crack_operand(
525: char *str,
526: struct m68k_op *opP);
527: static int get_num(
528: struct m68k_exp *exp,
529: int ok);
530:
531: /* JF modified this to handle cases where the first part of a symbol name
532: looks like a register */
533:
534: static
535: int
536: m68k_reg_parse(
537: char **ccp)
538: {
539: register char c1,
540: c2,
541: c3,
542: c4;
543: #ifdef BUILTIN_MMUS
544: char c5;
545: #endif
546: register int n = 0,
547: ret = 0;
548:
549: c1=mklower(ccp[0][0]);
550: c2=mklower(ccp[0][1]);
551: c3=mklower(ccp[0][2]);
552: c4=mklower(ccp[0][3]);
553: #ifdef BUILTIN_MMUS
554: c5=mklower(ccp[0][4]);
555: #endif
556:
557: switch(c1) {
558: case 'a':
559: if(c2>='0' && c2<='7') {
560: n=2;
561: ret=ADDR+c2-'0';
562: }
563: #ifdef m68851
564: else if (c2 == 'c') {
565: n = 2;
566: ret = AC;
567: }
568: #endif
569: break;
570: #ifdef m68851
571: case 'b':
572: if (c2 == 'a') {
573: if (c3 == 'd') {
574: if (c4 >= '0' && c4 <= '7') {
575: n = 4;
576: ret = BAD + c4 - '0';
577: }
578: }
579: if (c3 == 'c') {
580: if (c4 >= '0' && c4 <= '7') {
581: n = 4;
582: ret = BAC + c4 - '0';
583: }
584: }
585: }
586: break;
587: #endif
588: #ifdef BUILTIN_MMUS
589: case 'b':
590: if (c2 == 'c') {
591: n = 2;
592: ret = (BC);
593: }
594: break;
595: #endif
596: case 'c':
597: #ifdef m68851
598: if (c2 == 'a' && c3 == 'l') {
599: n = 3;
600: ret = CAL;
601: } else
602: #endif
603: /* This supports both CCR and CC as the ccr reg. */
604: if(c2=='c' && c3=='r') {
605: n=3;
606: ret = CCR;
607: } else if(c2=='c') {
608: n=2;
609: ret = CCR;
610: } else if(c2=='a' && (c3=='a' || c3=='c') && c4=='r') {
611: n=4;
612: ret = c3=='a' ? CAAR : CACR;
613: }
614: #if defined(m68851) || defined (BUILTIN_MMUS)
615: else if (c2 == 'r' && c3 == 'p') {
616: n = 3;
617: ret = (CRP);
618: }
619: #endif
620: break;
621: case 'd':
622: if(c2>='0' && c2<='7') {
623: n=2;
624: ret = DATA+c2-'0';
625: } else if(c2=='f' && c3=='c') {
626: n=3;
627: ret = DFC;
628: }
629: #ifdef m68851
630: else if (c2 == 'r' && c3 == 'p') {
631: n = 3;
632: ret = (DRP);
633: }
634: #endif
635: #ifdef BUILTIN_MMUS
636: else if (c2 == 't' && c3 == 't' && (c4 == '0' || c4 == '1')) {
637: n = 4;
638: if(c4 == '0')
639: ret = (DTT0);
640: else
641: ret = (DTT1);
642: }
643: else if (c2 == 'c') {
644: n = 2;
645: ret = (DC);
646: }
647: #endif
648: break;
649: case 'f':
650: if(c2=='p') {
651: if(c3>='0' && c3<='7') {
652: n=3;
653: ret = FPREG+c3-'0';
654: if(c4==':')
655: ccp[0][3]=',';
656: } else if(c3=='i') {
657: n=3;
658: ret = FPI;
659: } else if(c3=='s') {
660: n= (c4 == 'r' ? 4 : 3);
661: ret = FPS;
662: } else if(c3=='c') {
663: n= (c4 == 'r' ? 4 : 3);
664: ret = FPC;
665: }
666: }
667: break;
668: case 'i':
669: if(c2=='s' && c3=='p') {
670: n=3;
671: ret = ISP;
672: }
673: #ifdef BUILTIN_MMUS
674: else if (c2 == 't' && c3 == 't' && (c4 == '0' || c4 == '1')) {
675: n = 4;
676: if(c4 == '0')
677: ret = (ITT0);
678: else
679: ret = (ITT1);
680: }
681: else if (c2 == 'c') {
682: n = 2;
683: ret = (IC);
684: }
685: #endif
686: break;
687: case 'm':
688: if(c2=='s' && c3=='p') {
689: n=3;
690: ret = MSP;
691: }
692: #ifdef BUILTIN_MMUS
693: if(c2=='m' && c3=='u' && c4=='s' && c5=='r') {
694: n=5;
695: ret = MMUSR;
696: }
697: #endif
698: break;
699: case 'p':
700: if(c2=='c') {
701: #ifdef m68851
702: if(c3 == 's' && c4=='r') {
703: n=4;
704: ret = (PCSR);
705: } else
706: #endif
707: {
708: n=2;
709: ret = PC;
710: }
711: }
712: #ifdef m68851
713: else if (c2 == 's' && c3 == 'r') {
714: n = 3;
715: ret = (PSR);
716: }
717: #endif
718: #ifdef BUILTIN_MMUS
719: else if (c2 == 's' && c3 == 'r') {
720: n = 3;
721: ret = (MMUSR);
722: }
723: #endif
724: break;
725: case 's':
726: #if defined(m68851) || defined(BUILTIN_MMUS)
727: if (c2 == 'r' && c3 == 'p') {
728: n = 3;
729: ret = (SRP);
730: }
731: #endif
732: #ifdef m68851
733: else if (c2 == 'c' && c3 == 'c') {
734: n = 3;
735: ret = (SCC);
736: }
737: #endif
738: #if defined(m68851) || defined(BUILTIN_MMUS)
739: else
740: #endif
741: if(c2=='r') {
742: n=2;
743: ret = SR;
744: } else if(c2=='p') {
745: n=2;
746: ret = ADDR+7;
747: } else if(c2=='f' && c3=='c') {
748: n=3;
749: ret = SFC;
750: }
751: break;
752: #if defined(m68851) || defined(BUILTIN_MMUS)
753: case 't':
754: if(c2 == 'c') {
755: n=2;
756: ret=TC;
757: }
758: #ifdef BUILTIN_MMUS
759: else if (c2 == 't' && (c3 == '0' || c3 == '1')) {
760: n = 3;
761: if(c3 == '0')
762: ret = (TT0);
763: else
764: ret = (TT1);
765: }
766: #endif
767: break;
768: #endif
769: case 'u':
770: if(c2=='s' && c3=='p') {
771: n=3;
772: ret = USP;
773: }
774: #ifdef BUILTIN_MMUS
775: else if(c2=='r' && c3=='p') {
776: n=3;
777: ret = URP;
778: }
779: #endif
780: break;
781: case 'v':
782: #ifdef m68851
783: if (c2 == 'a' && c3 == 'l') {
784: n = 3;
785: ret = (VAL);
786: } else
787: #endif
788: if(c2=='b' && c3=='r') {
789: n=3;
790: ret = VBR;
791: }
792: break;
793: case 'z':
794: if(c2=='p' && c3=='c') {
795: n=3;
796: ret = ZPC;
797: }
798: break;
799: default:
800: break;
801: }
802: if(n) {
803: if(isalnum(ccp[0][n]) || ccp[0][n]=='_')
804: ret=FAIL;
805: else
806: ccp[0]+=n;
807: } else
808: ret = FAIL;
809: return ret;
810: }
811:
812: #define SKIP_WHITE() { str++; if(*str==' ') str++;}
813:
814: static
815: int
816: m68k_ip_op(
817: char *str,
818: struct m68k_op *opP)
819: {
820: char *strend;
821: long i;
822:
823: if(*str==' ')
824: str++;
825: /* Find the end of the string */
826: if(!*str) {
827: /* Out of gas */
828: opP->error="Missing operand";
829: return FAIL;
830: }
831: for(strend=str;*strend;strend++)
832: ;
833: --strend;
834:
835: /* Guess what: A constant. Shar and enjoy */
836: if(*str=='#') {
837: str++;
838: opP->con1=add_exp(str,strend);
839: opP->mode=IMMED;
840: return OK;
841: }
842: i=m68k_reg_parse(&str);
843: if((i==FAIL || *str!='\0') && *str!='@') {
844: char *stmp;
845:
846: if(i!=FAIL && (*str=='/' || *str=='-')) {
847: opP->mode=REGLST;
848: return get_regs(i,opP,str);
849: }
850: if((stmp=index(str,'@'))) {
851: opP->con1=add_exp(str,stmp-1);
852: if(stmp==strend) {
853: opP->mode=AINDX;
854: return OK;
855: }
856: stmp++;
857: if(*stmp++!='(' || *strend--!=')') {
858: opP->error="Malformed operand";
859: return FAIL;
860: }
861: i=try_index(&stmp,opP);
862: opP->con2=add_exp(stmp,strend);
863: if(i==FAIL) opP->mode=AMIND;
864: else opP->mode=APODX;
865: return OK;
866: }
867: opP->mode=ABSL;
868: opP->con1=add_exp(str,strend);
869: return OK;
870: }
871: opP->reg=i;
872: if(*str=='\0') {
873: if(i>=DATA+0 && i<=DATA+7)
874: opP->mode=DREG;
875: else if(i>=ADDR+0 && i<=ADDR+7)
876: opP->mode=AREG;
877: else
878: opP->mode=MSCR;
879: return OK;
880: }
881: if((i<ADDR+0 || i>ADDR+7) && i!=PC && i!=ZPC && i!=FAIL) { /* Can't indirect off non address regs */
882: opP->error="Invalid indirect register";
883: return FAIL;
884: }
885: if(*str!='@')
886: abort();
887: str++;
888: switch(*str) {
889: case '\0':
890: opP->mode=AINDR;
891: return OK;
892: case '-':
893: opP->mode=ADEC;
894: return OK;
895: case '+':
896: opP->mode=AINC;
897: return OK;
898: case '(':
899: str++;
900: break;
901: default:
902: opP->error="Junk after indirect";
903: return FAIL;
904: }
905: /* Some kind of indexing involved. Lets find out how bad it is */
906: i=try_index(&str,opP);
907: /* Didn't start with an index reg, maybe its offset or offset,reg */
908: if(i==FAIL) {
909: char *beg_str;
910:
911: beg_str=str;
912: for(i=1;i;) {
913: switch(*str++) {
914: case '\0':
915: opP->error="Missing )";
916: return FAIL;
917: case ',': i=0; break;
918: case '(': i++; break;
919: case ')': --i; break;
920: }
921: }
922: opP->con1=add_exp(beg_str,str-2);
923: /* Should be offset,reg */
924: if(str[-1]==',') {
925: i=try_index(&str,opP);
926: if(i==FAIL) {
927: opP->error="Malformed index reg";
928: return FAIL;
929: }
930: }
931: }
932: /* We've now got offset) offset,reg) or reg) */
933:
934: if(*str=='\0') {
935: /* Th-the-thats all folks */
936: #ifdef NeXT
937: /* all forms using zpc must use pc@(bd,Xn) and not pc@(d16) because
938: you can only suppress the base register in the first form */
939: if(opP->reg==FAIL || opP->reg==ZPC) opP->mode=AINDX; /* Other form of indirect */
940: #else /* !defined(NeXT) */
941: if(opP->reg==FAIL) opP->mode=AINDX; /* Other form of indirect */
942: #endif /* NeXT */
943: else if(opP->ireg==FAIL) opP->mode=AOFF;
944: else opP->mode=AINDX;
945: return OK;
946: }
947: /* Next thing had better be another @ */
948: if(*str!='@' || str[1]!='(') {
949: opP->error="junk after indirect";
950: return FAIL;
951: }
952: str+=2;
953: if(opP->ireg!=FAIL) {
954: opP->mode=APRDX;
955: i=try_index(&str,opP);
956: if(i!=FAIL) {
957: opP->error="Two index registers! not allowed!";
958: return FAIL;
959: }
960: } else
961: i=try_index(&str,opP);
962: if(i==FAIL) {
963: char *beg_str;
964:
965: beg_str=str;
966: for(i=1;i;) {
967: switch(*str++) {
968: case '\0':
969: opP->error="Missing )";
970: return FAIL;
971: case ',': i=0; break;
972: case '(': i++; break;
973: case ')': --i; break;
974: }
975: }
976: opP->con2=add_exp(beg_str,str-2);
977: if(str[-1]==',') {
978: if(opP->ireg!=FAIL) {
979: opP->error="Can't have two index regs";
980: return FAIL;
981: }
982: i=try_index(&str,opP);
983: if(i==FAIL) {
984: opP->error="malformed index reg";
985: return FAIL;
986: }
987: opP->mode=APODX;
988: } else if(opP->ireg!=FAIL)
989: opP->mode=APRDX;
990: else
991: opP->mode=AMIND;
992: } else
993: opP->mode=APODX;
994: if(*str!='\0') {
995: opP->error="Junk after indirect";
996: return FAIL;
997: }
998: return OK;
999: }
1000:
1001: static
1002: int
1003: try_index(
1004: char **s,
1005: struct m68k_op *opP)
1006: {
1007: register int i;
1008: char *ss;
1009: #define SKIP_W() { ss++; if(*ss==' ') ss++;}
1010:
1011: ss= *s;
1012: /* SKIP_W(); */
1013: i=m68k_reg_parse(&ss);
1014: if(!(i>=DATA+0 && i<=ADDR+7)) { /* if i is not DATA or ADDR reg */
1015: *s=ss;
1016: return FAIL;
1017: }
1018: opP->ireg=i;
1019: /* SKIP_W(); */
1020: if(*ss==')') {
1021: opP->isiz=0;
1022: opP->imul=1;
1023: SKIP_W();
1024: *s=ss;
1025: return OK;
1026: }
1027: if(*ss!=':') {
1028: opP->error="Missing : in index register";
1029: *s=ss;
1030: return FAIL;
1031: }
1032: SKIP_W();
1033: if(mklower(*ss)=='w') opP->isiz=2;
1034: else if(mklower(*ss)=='l') opP->isiz=3;
1035: else {
1036: opP->error="Size spec not :w or :l";
1037: *s=ss;
1038: return FAIL;
1039: }
1040: SKIP_W();
1041: if(*ss==':') {
1042: SKIP_W();
1043: switch(*ss) {
1044: case '1':
1045: case '2':
1046: case '4':
1047: case '8':
1048: opP->imul= *ss-'0';
1049: break;
1050: default:
1051: opP->error="index multiplier not 1, 2, 4 or 8";
1052: *s=ss;
1053: return FAIL;
1054: }
1055: SKIP_W();
1056: } else opP->imul=1;
1057: if(*ss!=')') {
1058: opP->error="Missing )";
1059: *s=ss;
1060: return FAIL;
1061: }
1062: SKIP_W();
1063: *s=ss;
1064: return OK;
1065: }
1066:
1067: #ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */
1068: void
1069: main(
1070: int argc,
1071: char *argv[],
1072: char *envp[])
1073: {
1074: char buf[128];
1075: struct m68k_op thark;
1076:
1077: for(;;){
1078: if(!gets(buf))
1079: break;
1080: memset(&thark, '\0', sizeof(thark));
1081: if(!m68k_ip_op(buf, &thark))
1082: printf("FAIL:");
1083: if(thark.error)
1084: printf("op1 error %s in %s\n",thark.error,buf);
1085: printf("mode %d, reg %d, ",thark.mode,thark.reg);
1086: if(thark.con1)
1087: printf("con1: '%.*s',",
1088: 1 + thark.con1->e_end - thark.con1->e_beg,
1089: thark.con1->e_beg);
1090: printf("ireg %d, isiz %d, imul %d ",
1091: thark.ireg, thark.isiz, thark.imul);
1092: if(thark.con2)
1093: printf("con2: '%.*s'",
1094: 1 + thark.con2->e_end - thark.con2->e_beg,
1095: thark.con2->e_beg);
1096: printf("\n");
1097: }
1098: exit(0);
1099: }
1100: #endif /* TEST1 */
1101:
1102:
1103: /*
1104: * Handle of the OPCODE hash table NULL means any use before m68_ip_begin()
1105: * will crash.
1106: */
1107: static struct hash_control *op_hash = NULL;
1108:
1109:
1110: /*
1111: * m 6 8 _ i p ( )
1112: *
1113: * This converts a string into a 68k instruction.
1114: * The string must be a bare single instruction in sun format
1115: * with RMS-style 68020 indirects
1116: * (example: )
1117: *
1118: * It provides some error messages: at most one fatal error message (which
1119: * stops the scan) and at most one warning message for each operand.
1120: * The 68k instruction is returned in exploded form, since we have no
1121: * knowledge of how you parse (or evaluate) your expressions.
1122: * We do however strip off and decode addressing modes and operation
1123: * mnemonic.
1124: *
1125: * This function's value is a string. If it is not "" then an internal
1126: * logic error was found: read this code to assign meaning to the string.
1127: * No argument string should generate such an error string:
1128: * it means a bug in our code, not in the user's text.
1129: *
1130: * You MUST have called m86_ip_begin() once and m86_ip_end() never before using
1131: * this function.
1132: */
1133:
1134: /* JF this function no longer returns a useful value. Sorry */
1135: static
1136: void
1137: m68_ip(
1138: char *instring)
1139: {
1140: register char *p;
1141: register struct m68k_op *opP;
1142: register struct m68_incant *opcode;
1143: register char *s;
1144: register int tmpreg = 0,
1145: baseo = 0,
1146: outro = 0,
1147: nextword;
1148: int siz1,
1149: siz2;
1150: char c;
1151: int losing;
1152: int opsfound;
1153: LITTLENUM_TYPE words[6];
1154: LITTLENUM_TYPE *wordp;
1155:
1156: if (*instring == ' ')
1157: instring++; /* skip leading whitespace */
1158:
1159: /* Scan up to end of operation-code, which MUST end in end-of-string
1160: or exactly 1 space. */
1161: for (p = instring; *p != '\0'; p++)
1162: if (*p == ' ')
1163: break;
1164:
1165:
1166: if (p == instring) {
1167: the_ins.error = "No operator";
1168: the_ins.opcode[0] = 0;
1169: /* the_ins.numo=1; */
1170: return;
1171: }
1172:
1173: /* p now points to the end of the opcode name, probably whitespace.
1174: make sure the name is null terminated by clobbering the whitespace,
1175: look it up in the hash table, then fix it back. */
1176: c = *p;
1177: *p = '\0';
1178: opcode = (struct m68_incant *)hash_find (op_hash, instring);
1179: *p = c;
1180:
1181: if (opcode == NULL) {
1182: the_ins.error = "Unknown operator";
1183: the_ins.opcode[0] = 0;
1184: /* the_ins.numo=1; */
1185: return;
1186: }
1187:
1188: /* found a legitimate opcode, start matching operands */
1189: for(opP= &the_ins.operands[0];*p;opP++) {
1190: p = crack_operand (p, opP);
1191: if(opP->error) {
1192: the_ins.error=opP->error;
1193: return;
1194: }
1195: }
1196:
1197: opsfound=opP- &the_ins.operands[0];
1198: /* This ugly hack is to support the floating pt opcodes in their standard form */
1199: /* Essentially, we fake a first enty of type COP#1 */
1200: if(opcode->m_operands[0]=='I') {
1201: int n;
1202:
1203: for(n=opsfound;n>0;--n)
1204: the_ins.operands[n]=the_ins.operands[n-1];
1205:
1206: /* bcopy((char *)(&the_ins.operands[0]),(char *)(&the_ins.operands[1]),opsfound*sizeof(the_ins.operands[0])); */
1207: memset((char *)(&the_ins.operands[0]), '\0',
1208: sizeof(the_ins.operands[0]));
1209: the_ins.operands[0].mode=MSCR;
1210: the_ins.operands[0].reg=COPNUM; /* COP #1 */
1211: opsfound++;
1212: }
1213: /* We've got the operands. Find an opcode that'll
1214: accept them */
1215: for(losing=0;;) {
1216: if(opsfound!=opcode->m_opnum)
1217: losing++;
1218: else for(s=opcode->m_operands,opP= &the_ins.operands[0];*s && !losing;s+=2,opP++) {
1219: /* Warning: this switch is huge! */
1220: /* I've tried to organize the cases into this order:
1221: non-alpha first, then alpha by letter. lower-case goes directly
1222: before uppercase counterpart. */
1223: /* Code with multiple case ...: gets sorted by the lowest case ...
1224: it belongs to. I hope this makes sense. */
1225: switch(*s) {
1226: case '!':
1227: if(opP->mode==MSCR || opP->mode==IMMED ||
1228: opP->mode==DREG || opP->mode==AREG || opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
1229: losing++;
1230: break;
1231:
1232: case '#':
1233: if(opP->mode!=IMMED)
1234: losing++;
1235: else {
1236: long t;
1237:
1238: t=get_num(opP->con1,80);
1239: if(s[1]=='b' && !isbyte(t))
1240: losing++;
1241: #ifdef CHECK_WORD_IMMEDIATES
1242: else if((s[1]=='w' || s[1]=='z') &&
1243: !isword(t))
1244: losing++;
1245: #else
1246: else if(s[1]=='z' && !isword(t))
1247: losing++;
1248: #endif
1249: }
1250: break;
1251:
1252: case '^':
1253: case 'T':
1254: if(opP->mode!=IMMED)
1255: losing++;
1256: break;
1257:
1258: case '$':
1259: if(opP->mode==MSCR || opP->mode==AREG ||
1260: opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
1261: losing++;
1262: break;
1263:
1264: case '%':
1265: if(opP->mode==MSCR || opP->reg==PC ||
1266: opP->reg==ZPC || opP->mode==REGLST)
1267: losing++;
1268: break;
1269:
1270:
1271: case '&':
1272: if(opP->mode==MSCR || opP->mode==DREG ||
1273: opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC ||
1274: opP->mode==AINC || opP->mode==ADEC || opP->mode==REGLST)
1275: losing++;
1276: break;
1277:
1278: case '*':
1279: if(opP->mode==MSCR || opP->mode==REGLST)
1280: losing++;
1281: break;
1282:
1283: case '+':
1284: if(opP->mode!=AINC)
1285: losing++;
1286: break;
1287:
1288: case '-':
1289: if(opP->mode!=ADEC)
1290: losing++;
1291: break;
1292:
1293: #ifdef NeXT
1294: case '0':
1295: if(opP->mode!=AINDR)
1296: losing++;
1297: break;
1298: #endif /* NeXT */
1299:
1300: case '/':
1301: if(opP->mode==MSCR || opP->mode==AREG ||
1302: opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->mode==REGLST)
1303: losing++;
1304: break;
1305:
1306: case ';':
1307: if(opP->mode==MSCR || opP->mode==AREG || opP->mode==REGLST)
1308: losing++;
1309: break;
1310:
1311: case '?':
1312: if(opP->mode==MSCR || opP->mode==AREG ||
1313: opP->mode==AINC || opP->mode==ADEC || opP->mode==IMMED || opP->reg==PC ||
1314: opP->reg==ZPC || opP->mode==REGLST)
1315: losing++;
1316: break;
1317:
1318: case '@':
1319: if(opP->mode==MSCR || opP->mode==AREG ||
1320: opP->mode==IMMED || opP->mode==REGLST)
1321: losing++;
1322: break;
1323:
1324: case '~': /* For now! (JF FOO is this right?) */
1325: if(opP->mode==MSCR || opP->mode==DREG ||
1326: opP->mode==AREG || opP->mode==IMMED || opP->reg==PC || opP->reg==ZPC || opP->mode==REGLST)
1327: losing++;
1328: break;
1329:
1330: case 'A':
1331: if(opP->mode!=AREG)
1332: losing++;
1333: break;
1334:
1335: case 'B': /* FOO */
1336: if(opP->mode!=ABSL)
1337: losing++;
1338: break;
1339:
1340: case 'C':
1341: if(opP->mode!=MSCR || opP->reg!=CCR)
1342: losing++;
1343: break;
1344:
1345: case 'd': /* FOO This mode is a KLUDGE!! */
1346: if(opP->mode!=AOFF && (opP->mode!=ABSL ||
1347: opP->con1->e_beg[0]!='(' || opP->con1->e_end[0]!=')'))
1348: losing++;
1349: break;
1350:
1351: case 'D':
1352: if(opP->mode!=DREG)
1353: losing++;
1354: break;
1355:
1356: case 'F':
1357: if(opP->mode!=MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7))
1358: losing++;
1359: break;
1360:
1361: case 'I':
1362: if(opP->mode!=MSCR || opP->reg<COPNUM ||
1363: opP->reg>=COPNUM+7)
1364: losing++;
1365: break;
1366:
1367: case 'J':
1368: #ifdef BUILTIN_MMUS
1369: if(opP->mode!=MSCR || opP->reg<USP || opP->reg>SRP)
1370: #else
1371: if(opP->mode!=MSCR || opP->reg<USP || opP->reg>MSP)
1372: #endif
1373: losing++;
1374: break;
1375:
1376: case 'k':
1377: if(opP->mode!=IMMED)
1378: losing++;
1379: break;
1380:
1381: case 'l':
1382: case 'L':
1383: if(opP->mode==DREG || opP->mode==AREG || opP->mode==FPREG) {
1384: if(s[1]=='8')
1385: losing++;
1386: else {
1387: opP->mode=REGLST;
1388: opP->reg=1<<(opP->reg-DATA);
1389: }
1390: } else if(opP->mode!=REGLST) {
1391: losing++;
1392: } else if(s[1]=='8' && opP->reg&0x0FFffFF)
1393: losing++;
1394: else if(s[1]=='3' && opP->reg&0x7000000)
1395: losing++;
1396: break;
1397:
1398: case 'M':
1399: if(opP->mode!=IMMED)
1400: losing++;
1401: else {
1402: long t;
1403:
1404: t=get_num(opP->con1,80);
1405: #ifdef NeXT /* feature to try to make expressions absolute */
1406: /* DJA -- Bug fix. allow absolute expressions */
1407: if(! (issbyte(t) && seg(opP->con1)==SEG_ABSOLUTE) )
1408: #else /* !defined(NeXT) */
1409: if(!issbyte(t) || isvar(opP->con1))
1410: #endif /* NeXT */
1411: losing++;
1412: }
1413: break;
1414:
1415: case 'O':
1416: if(opP->mode!=DREG && opP->mode!=IMMED)
1417: losing++;
1418: break;
1419:
1420: case 'Q':
1421: if(opP->mode!=IMMED)
1422: losing++;
1423: else {
1424: long t;
1425:
1426: t=get_num(opP->con1,80);
1427: if(t<1 || t>8 || isvar(opP->con1))
1428: losing++;
1429: }
1430: break;
1431:
1432: case 'R':
1433: if(opP->mode!=DREG && opP->mode!=AREG)
1434: losing++;
1435: break;
1436:
1437: case 's':
1438: if(opP->mode!=MSCR || !(opP->reg==FPI || opP->reg==FPS || opP->reg==FPC))
1439: losing++;
1440: break;
1441:
1442: case 'S':
1443: if(opP->mode!=MSCR || opP->reg!=SR)
1444: losing++;
1445: break;
1446:
1447: case 'U':
1448: if(opP->mode!=MSCR || opP->reg!=USP)
1449: losing++;
1450: break;
1451:
1452: /* JF these are out of order. We could put them
1453: in order if we were willing to put up with
1454: bunches of #ifdef m68851s in the code */
1455: #ifdef m68851
1456: /* Memory addressing mode used by pflushr */
1457: case '|':
1458: if(opP->mode==MSCR || opP->mode==DREG ||
1459: opP->mode==AREG || opP->mode==REGLST)
1460: losing++;
1461: break;
1462: #endif
1463:
1464: #if defined(m68851) || defined(BUILTIN_MMUS)
1465: case 'f':
1466: if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC))
1467: losing++;
1468: break;
1469: #endif
1470:
1471: #ifdef m68851
1472: case 'P':
1473: if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL &&
1474: opP->reg != VAL && opP->reg != SCC && opP->reg != AC))
1475: losing++;
1476: break;
1477:
1478: case 'V':
1479: if (opP->reg != VAL)
1480: losing++;
1481: break;
1482:
1483: case 'W':
1484: if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP &&
1485: opP->reg != CRP))
1486: losing++;
1487: break;
1488:
1489: case 'X':
1490: if (opP->mode != MSCR ||
1491: (!(opP->reg >= BAD && opP->reg <= BAD+7) &&
1492: !(opP->reg >= BAC && opP->reg <= BAC+7)))
1493: losing++;
1494: break;
1495:
1496: case 'Y':
1497: if (opP->reg != PSR)
1498: losing++;
1499: break;
1500:
1501: case 'Z':
1502: if (opP->reg != PCSR)
1503: losing++;
1504: break;
1505: #endif
1506: #ifdef BUILTIN_MMUS
1507: case 'a':
1508: if ((opP->mode != MSCR) || (opP->reg != SRP &&
1509: opP->reg != CRP && opP->reg != TC))
1510: losing++;
1511: break;
1512: case 'b':
1513: if (opP->mode != MSCR || opP->reg != MMUSR)
1514: losing++;
1515: break;
1516: case 'c':
1517: if ((opP->mode != MSCR) || (opP->reg != IC &&
1518: opP->reg != DC && opP->reg != BC))
1519: losing++;
1520: break;
1521: case 'e':
1522: if ((opP->mode != MSCR) || (opP->reg != TT0 &&
1523: opP->reg != TT1))
1524: losing++;
1525: break;
1526: #endif
1527: default:
1528: as_fatal("Internal error: Operand mode %c unknown",*s);
1529: }
1530: }
1531: if(!losing)
1532: break;
1533: opcode=opcode->m_next;
1534: if(!opcode) { /* Fell off the end */
1535: the_ins.error="instruction/operands mismatch";
1536: return;
1537: }
1538: losing=0;
1539: }
1540: the_ins.args=opcode->m_operands;
1541: the_ins.numargs=opcode->m_opnum;
1542: the_ins.numo=opcode->m_codenum;
1543: the_ins.opcode[0]=getone(opcode);
1544: the_ins.opcode[1]=gettwo(opcode);
1545: #ifdef NeXT
1546: the_ins.cpus=opcode->m_cpus;
1547: #endif /* NeXT */
1548:
1549: for(s=the_ins.args,opP= &the_ins.operands[0];*s;s+=2,opP++) {
1550: /* This switch is a doozy.
1551: What the first step; its a big one! */
1552: switch(s[0]) {
1553:
1554: case '*':
1555: case '~':
1556: case '%':
1557: case ';':
1558: case '@':
1559: case '!':
1560: case '&':
1561: case '$':
1562: case '?':
1563: case '/':
1564: #ifdef m68851
1565: case '|':
1566: #endif
1567: switch(opP->mode) {
1568: case IMMED:
1569: tmpreg=0x3c; /* 7.4 */
1570: if(index("bwzl",s[1]))
1571: nextword=get_num(opP->con1,80);
1572: else
1573: nextword=get_num(opP->con1,0);
1574: if(isvar(opP->con1))
1575: add_fix(s[1],opP->con1,0);
1576: switch(s[1]) {
1577: case 'b':
1578: if(!isbyte(nextword))
1579: opP->error="operand out of range";
1580: addword(nextword);
1581: baseo=0;
1582: break;
1583: case 'w':
1584: case 'z':
1585: #ifdef CHECK_WORD_IMMEDIATES
1586: if(!isword(nextword))
1587: opP->error="operand out of range";
1588: #endif
1589: addword(nextword);
1590: baseo=0;
1591: break;
1592: #ifdef NeXT /* Used in the fmoveml (control) registers */
1593: case 's':
1594: #endif /* NeXT */
1595: case 'l':
1596: addword(nextword>>16);
1597: addword(nextword);
1598: baseo=0;
1599: break;
1600:
1601: case 'f':
1602: baseo=2;
1603: outro=8;
1604: break;
1605: case 'F':
1606: baseo=4;
1607: outro=11;
1608: break;
1609: case 'x':
1610: baseo=6;
1611: outro=15;
1612: break;
1613: #ifdef PACKED_IMMEDIATE
1614: /* This does not work. The call to gen_to_words() below does not put out
1615: 68k packed decimal format. */
1616: case 'p':
1617: baseo=6;
1618: outro= -1;
1619: break;
1620: #endif
1621: default:
1622: as_fatal("Internal error: Can't decode %c%c",*s,s[1]);
1623: }
1624: if(!baseo)
1625: break;
1626:
1627: /* We gotta put out some float */
1628: if(seg(opP->con1)!=SEG_BIG) {
1629: int_to_gen(nextword);
1630: gen_to_words(words,baseo,(long int)outro);
1631: for(wordp=words;baseo--;wordp++)
1632: addword(*wordp);
1633: break;
1634: } /* Its BIG */
1635: if(offs(opP->con1)>0) {
1636: #ifndef NeXT /* fix for bug #8331 */
1637: as_warn("Bignum assumed to be binary bit-pattern");
1638: #endif /* NeXT */
1639: if(offs(opP->con1)>baseo) {
1640: as_warn("Bignum too big for %c format; truncated",s[1]);
1641: offs(opP->con1)=baseo;
1642: }
1643: baseo-=offs(opP->con1);
1644: for(wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp)
1645: addword(*wordp);
1646: while(baseo--)
1647: addword(0);
1648: break;
1649: }
1650: gen_to_words(words,baseo,(long int)outro);
1651: for(wordp=words;baseo--;wordp++)
1652: addword(*wordp);
1653: break;
1654: case DREG:
1655: tmpreg=opP->reg-DATA; /* 0.dreg */
1656: break;
1657: case AREG:
1658: tmpreg=0x08+opP->reg-ADDR; /* 1.areg */
1659: break;
1660: case AINDR:
1661: #ifdef NeXT
1662: /* fixes "pc@" operand */
1663: if(opP->reg==PC){
1664: tmpreg=0x3A; /* 7.2 */
1665: addword(0x0000);
1666: }
1667: else
1668: #endif /* NeXT */
1669: tmpreg=0x10+opP->reg-ADDR; /* 2.areg */
1670: break;
1671: case ADEC:
1672: tmpreg=0x20+opP->reg-ADDR; /* 4.areg */
1673: break;
1674: case AINC:
1675: tmpreg=0x18+opP->reg-ADDR; /* 3.areg */
1676: break;
1677: case AOFF:
1678: if(opP->reg==PC)
1679: tmpreg=0x3A; /* 7.2 */
1680: else
1681: tmpreg=0x28+opP->reg-ADDR; /* 5.areg */
1682: nextword=get_num(opP->con1,80);
1683: /* Force into index mode. Hope this works */
1684: if(!issword(nextword)) {
1685: if(opP->reg==PC)
1686: tmpreg=0x3B; /* 7.3 */
1687: else
1688: tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
1689: /* addword(0x0171); */
1690: /* 171 seems to be wrong, and I can't find the 68020 manual, so we'll try 170
1691: (which is what the Sun asm seems to generate */
1692: addword(0x0170);
1693: if(isvar(opP->con1))
1694: add_fix('l',opP->con1,0);
1695: addword(nextword>>16);
1696: /* addword(nextword); */
1697: } else if(isvar(opP->con1)) {
1698: if(!flagseen['l'] &&
1699: flagseen['k'] &&
1700: seg(opP->con1) != SEG_DIFFSECT)
1701: {
1702: add_fix('w',opP->con1,0);
1703: } else {
1704: if(opP->reg==PC)
1705: tmpreg=0x3B; /* 7.3 */
1706: else
1707: tmpreg=0x30+opP->reg-ADDR;
1708: addword(0x0170);
1709: /*
1710: * If this is a pc register with
1711: * a SEGDIFF where the -symbol
1712: * is "." adjust the value of
1713: * of "." to include the two
1714: * bytes of opcode.
1715: */
1716: if(opP->reg==PC &&
1717: seg(opP->con1) ==
1718: SEG_DIFFSECT &&
1719: opP->con1->
1720: e_exp.X_subtract_symbol->
1721: sy_frag == frag_now &&
1722: strcmp(opP->con1->
1723: e_exp.X_subtract_symbol->
1724: sy_nlist.n_un.n_name,
1725: "L0\001") == 0)
1726: opP->con1->
1727: e_exp.X_subtract_symbol->
1728: sy_nlist.n_value += 2;
1729: add_fix('l',opP->con1,0);
1730: addword(nextword>>16);
1731: }
1732: }
1733: addword(nextword);
1734: break;
1735: case AINDX:
1736: case APODX:
1737: case AMIND:
1738: case APRDX:
1739: nextword=0;
1740: baseo=get_num(opP->con1,80);
1741: outro=get_num(opP->con2,80);
1742: /* Figure out the 'addressing mode' */
1743: /* Also turn on the BASE_DISABLE bit, if needed */
1744: if(opP->reg==PC || opP->reg==ZPC) {
1745: tmpreg=0x3b; /* 7.3 */
1746: if(opP->reg==ZPC)
1747: nextword|=0x80;
1748: } else if(opP->reg==FAIL) {
1749: nextword|=0x80;
1750: tmpreg=0x30; /* 6.garbage */
1751: } else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
1752:
1753: siz1= (opP->con1) ? opP->con1->e_siz : 0;
1754: siz2= (opP->con2) ? opP->con2->e_siz : 0;
1755:
1756: /* Index register stuff */
1757: if(opP->ireg>=DATA+0 && opP->ireg<=ADDR+7) {
1758: nextword|=(opP->ireg-DATA)<<12;
1759:
1760: if(opP->isiz==0 || opP->isiz==3)
1761: nextword|=0x800;
1762: switch(opP->imul) {
1763: case 1: break;
1764: case 2: nextword|=0x200; break;
1765: case 4: nextword|=0x400; break;
1766: case 8: nextword|=0x600; break;
1767: default: abort();
1768: }
1769: /* IF its simple, GET US OUT OF HERE! */
1770: /* Must be INDEX, with an index register. Address register
1771: cannot be ZERO-PC, and either :b was forced, or we know it'll fit */
1772: if(opP->mode==AINDX &&
1773: opP->reg!=FAIL && opP->reg!=ZPC && (siz1==1 || (issbyte(baseo) &&
1774: !isvar(opP->con1)))) {
1775: nextword +=baseo&0xff;
1776: addword(nextword);
1777: if(isvar(opP->con1))
1778: add_fix('B',opP->con1,0);
1779: break;
1780: }
1781: } else
1782: nextword|=0x40; /* No index reg */
1783:
1784: /* It aint simple */
1785: nextword|=0x100;
1786: /* If the guy specified a width, we assume that
1787: it is wide enough. Maybe it isn't. Ifso, we lose
1788: */
1789: switch(siz1) {
1790: case 0:
1791: if(isvar(opP->con1) || !issword(baseo)) {
1792: siz1=3;
1793: nextword|=0x30;
1794: } else if(baseo==0)
1795: nextword|=0x10;
1796: else {
1797: nextword|=0x20;
1798: siz1=2;
1799: }
1800: break;
1801: case 1:
1802: as_warn("Byte dispacement won't work. Defaulting to :w");
1803: case 2:
1804: nextword|=0x20;
1805: break;
1806: case 3:
1807: nextword|=0x30;
1808: break;
1809: }
1810:
1811: /* Figure out innner displacement stuff */
1812: if(opP->mode!=AINDX) {
1813: switch(siz2) {
1814: case 0:
1815: if(isvar(opP->con2) || !issword(outro)) {
1816: siz2=3;
1817: nextword|=0x3;
1818: } else if(outro==0)
1819: nextword|=0x1;
1820: else {
1821: nextword|=0x2;
1822: siz2=2;
1823: }
1824: break;
1825: case 1:
1826: as_warn("Byte dispacement won't work. Defaulting to :w");
1827: case 2:
1828: nextword|=0x2;
1829: break;
1830: case 3:
1831: nextword|=0x3;
1832: break;
1833: }
1834: if(opP->mode==APODX) nextword|=0x04;
1835: else if(opP->mode==AMIND) nextword|=0x40;
1836: }
1837: addword(nextword);
1838:
1839: if(isvar(opP->con1))
1840: add_fix(siz1==3 ? 'l' : 'w',opP->con1,0);
1841: if(siz1==3)
1842: addword(baseo>>16);
1843: if(siz1)
1844: addword(baseo);
1845:
1846: if(isvar(opP->con2))
1847: add_fix(siz2==3 ? 'l' : 'w',opP->con2,0);
1848: if(siz2==3)
1849: addword(outro>>16);
1850: if(siz2)
1851: addword(outro);
1852:
1853: break;
1854:
1855: case ABSL:
1856: nextword=get_num(opP->con1,80);
1857: switch(opP->con1->e_siz) {
1858: case 1: /* treat like not there, fall through */
1859: as_warn("ignoring :b suffix on %*s",
1860: (int)(opP->con1->e_end-opP->con1->e_beg),
1861: opP->con1->e_beg);
1862: case 0:
1863: if(!isvar(opP->con1) &&
1864: issword(offs(opP->con1))) {
1865: tmpreg=0x38; /* 7.0 */
1866: addword(nextword);
1867: break;
1868: }
1869: /* Don't generate pc relative code
1870: on 68010 and 68000 */
1871: if(isvar(opP->con1) &&
1872: !subs(opP->con1) &&
1873: seg(opP->con1) == SEG_SECT &&
1874: frchain_now->frch_nsect ==
1875: opP->con1->e_exp.X_add_symbol->
1876: sy_nlist.n_sect &&
1877: flagseen['m'] == 0 &&
1878: !index("~%&$?", s[0])) {
1879: tmpreg=0x3A; /* 7.2 */
1880: add_frag(adds(opP->con1),
1881: offs(opP->con1),
1882: TAB(PCREL,SZ_UNDEF));
1883: break;
1884: }
1885: case 3: /* Fall through into long */
1886: if(isvar(opP->con1))
1887: add_fix('l',opP->con1,0);
1888:
1889: tmpreg=0x39; /* 7.1 mode */
1890: addword(nextword>>16);
1891: addword(nextword);
1892: break;
1893:
1894: case 2: /* Word */
1895: if(isvar(opP->con1))
1896: add_fix('w',opP->con1,0);
1897:
1898: tmpreg=0x38; /* 7.0 mode */
1899: addword(nextword);
1900: break;
1901: }
1902: break;
1903: case MSCR:
1904: default:
1905: as_bad("unknown/incorrect operand");
1906: /* abort(); */
1907: }
1908: install_gen_operand(s[1],tmpreg);
1909: break;
1910:
1911: case '#':
1912: case '^':
1913: switch(s[1]) { /* JF: I hate floating point! */
1914: case 'j':
1915: tmpreg=70;
1916: break;
1917: case '8':
1918: tmpreg=20;
1919: break;
1920: case 'C':
1921: tmpreg=50;
1922: break;
1923: case '3':
1924: default:
1925: tmpreg=80;
1926: break;
1927: }
1928: tmpreg=get_num(opP->con1,tmpreg);
1929: if(isvar(opP->con1))
1930: add_fix(s[1],opP->con1,0);
1931: switch(s[1]) {
1932: case 'b': /* Danger: These do no check for
1933: certain types of overflow.
1934: user beware! */
1935: if(!isbyte(tmpreg))
1936: opP->error="out of range";
1937: insop(tmpreg);
1938: if(isvar(opP->con1))
1939: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
1940: break;
1941: #ifdef NeXT
1942: case 'j':
1943: if(tmpreg < 0 || tmpreg > 0xfff)
1944: opP->error="out of range";
1945: tmpreg&=0xFFF;
1946: install_operand(s[1],tmpreg);
1947: break;
1948: #endif /* NeXT */
1949: case 'w':
1950: case 'z':
1951: #ifdef CHECK_WORD_IMMEDIATES
1952: if(!isword(tmpreg))
1953: opP->error="out of range";
1954: #endif
1955: insop(tmpreg);
1956: if(isvar(opP->con1))
1957: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
1958: break;
1959: case 'l':
1960: insop(tmpreg); /* Because of the way insop works, we put these two out backwards */
1961: insop(tmpreg>>16);
1962: if(isvar(opP->con1))
1963: the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
1964: break;
1965: case '3':
1966: tmpreg&=0xFF;
1967: #ifdef NeXT
1968: if (isvar(opP->con1))
1969: the_ins.reloc[the_ins.nrel-1].n =
1970: (opcode->m_codenum) + 1;
1971: #endif /* NeXT */
1972: case '8':
1973: case 'C':
1974: install_operand(s[1],tmpreg);
1975: break;
1976: default:
1977: as_fatal("Internal error: Unknown mode #%c",s[1]);
1978: }
1979: break;
1980:
1981: case '+':
1982: case '-':
1983: case 'A':
1984: install_operand(s[1],opP->reg-ADDR);
1985: break;
1986:
1987: case 'B':
1988: tmpreg = get_num(opP->con1, 80);
1989: switch(s[1]){
1990: case 'g':
1991: /* Deal with fixed size stuff by hand */
1992: if(opP->con1->e_siz){
1993: switch(opP->con1->e_siz){
1994: case 1:
1995: add_fix('B', opP->con1, 1);
1996: break;
1997: case 2:
1998: if(strncmp(instring, "jbsr", 4) == 0){
1999: if(isvar(opP->con1))
2000: add_fix('w', opP->con1, 0);
2001: /* force a jsr 7.0 mode (xxx):W */
2002: the_ins.opcode[the_ins.numo-1] = 0x4eb8;
2003: addword(tmpreg);
2004: break;
2005: }
2006: if(strncmp(instring, "jra", 3) == 0){
2007: if(isvar(opP->con1))
2008: add_fix('w', opP->con1, 0);
2009: /* force a jmp 7.0 mode (xxx):W */
2010: the_ins.opcode[the_ins.numo-1] = 0x4ef8;
2011: addword(tmpreg);
2012: break;
2013: }
2014: opP->con1->e_exp.X_add_number += 2;
2015: add_fix('w', opP->con1, 1);
2016: addword(0);
2017: break;
2018: case 3:
2019: the_ins.opcode[the_ins.numo-1] |= 0xff;
2020: opP->con1->e_exp.X_add_number += 4;
2021: add_fix('l', opP->con1, 1);
2022: addword(0);
2023: addword(0);
2024: break;
2025: default:
2026: as_fatal("Bad size for expression %d",
2027: opP->con1->e_siz);
2028: }
2029: }
2030: else if(subs(opP->con1)){
2031: /* We can't relax it */
2032: the_ins.opcode[the_ins.numo-1] |= 0xff;
2033: add_fix('l', opP->con1, 1);
2034: addword(0);
2035: addword(0);
2036: }
2037: else if(adds(opP->con1)){
2038: if(flagseen['m'] &&
2039: (the_ins.opcode[0] >= 0x6200) &&
2040: (the_ins.opcode[0] <= 0x6f00)){
2041: add_frag(adds(opP->con1),
2042: offs(opP->con1),
2043: TAB(BCC68000, SZ_UNDEF));
2044: }
2045: else{
2046: add_frag(adds(opP->con1),
2047: offs(opP->con1),
2048: TAB(BRANCH, SZ_UNDEF));
2049: }
2050: }
2051: else{
2052: the_ins.opcode[the_ins.numo-1] |= 0xff;
2053: opP->con1->e_exp.X_add_number += 4;
2054: add_fix('l', opP->con1, 1);
2055: addword(0);
2056: addword(0);
2057: }
2058: break;
2059: case 'w':
2060: if(isvar(opP->con1)){
2061: /* check for DBcc instruction */
2062: if((the_ins.opcode[0] & 0xf0f8) ==0x50c8){
2063: /* size varies if patch */
2064: /* needed for long form */
2065: add_frag(adds(opP->con1),
2066: offs(opP->con1),
2067: TAB(DBCC, SZ_UNDEF));
2068: break;
2069: }
2070: }
2071: opP->con1->e_exp.X_add_number += 2;
2072: add_fix('w', opP->con1, 1);
2073: addword(0);
2074: break;
2075: case 'c':
2076: if(opP->con1->e_siz){
2077: switch(opP->con1->e_siz){
2078: case 2:
2079: opP->con1->e_exp.X_add_number += 2;
2080: add_fix('w', opP->con1, 1);
2081: addword(0);
2082: break;
2083: case 3:
2084: the_ins.opcode[the_ins.numo-1] |= 0x40;
2085: opP->con1->e_exp.X_add_number += 4;
2086: add_fix('l', opP->con1, 1);
2087: addword(0);
2088: addword(0);
2089: break;
2090: default:
2091: as_bad("Bad size for offset, must be word "
2092: "or long");
2093: break;
2094: }
2095: }
2096: else if(subs(opP->con1)){
2097: /* We can't relax it */
2098: the_ins.opcode[the_ins.numo-1] |= 0x40;
2099: add_fix('l', opP->con1, 1);
2100: addword(0);
2101: addword(0);
2102: }
2103: else if(adds(opP->con1)){
2104: add_frag(adds(opP->con1),
2105: offs(opP->con1),
2106: TAB(FBRANCH, SZ_UNDEF));
2107: }
2108: else{
2109: the_ins.opcode[the_ins.numo-1] |= 0x40;
2110: opP->con1->e_exp.X_add_number += 4;
2111: add_fix('l', opP->con1, 1);
2112: addword(0);
2113: addword(0);
2114: }
2115: break;
2116: default:
2117: as_fatal("Internal error: operand type B%c unknown",
2118: s[1]);
2119: }
2120: break;
2121:
2122: case 'C': /* Ignore it */
2123: break;
2124:
2125: case 'd': /* JF this is a kludge */
2126: if(opP->mode==AOFF) {
2127: install_operand('s',opP->reg-ADDR);
2128: } else {
2129: char *tmpP;
2130:
2131: tmpP=opP->con1->e_end-2;
2132: opP->con1->e_beg++;
2133: opP->con1->e_end-=4; /* point to the , */
2134: baseo=m68k_reg_parse(&tmpP);
2135: if(baseo<ADDR+0 || baseo>ADDR+7) {
2136: as_bad("Unknown address reg, using A0");
2137: baseo=0;
2138: } else baseo-=ADDR;
2139: install_operand('s',baseo);
2140: }
2141: tmpreg=get_num(opP->con1,80);
2142: if(!issword(tmpreg)) {
2143: as_warn("Expression out of range, using 0");
2144: tmpreg=0;
2145: }
2146: addword(tmpreg);
2147: break;
2148:
2149: case 'D':
2150: install_operand(s[1],opP->reg-DATA);
2151: break;
2152:
2153: case 'F':
2154: install_operand(s[1],opP->reg-FPREG);
2155: break;
2156:
2157: case 'I':
2158: tmpreg=1+opP->reg-COPNUM;
2159: if(tmpreg==8)
2160: tmpreg=0;
2161: install_operand(s[1],tmpreg);
2162: break;
2163:
2164: case 'J': /* JF foo */
2165: switch(opP->reg) {
2166: case SFC:
2167: tmpreg=0;
2168: break;
2169: case DFC:
2170: tmpreg=0x001;
2171: break;
2172: case CACR:
2173: tmpreg=0x002;
2174: break;
2175: case USP:
2176: tmpreg=0x800;
2177: break;
2178: case VBR:
2179: tmpreg=0x801;
2180: break;
2181: case CAAR:
2182: tmpreg=0x802;
2183: break;
2184: case MSP:
2185: tmpreg=0x803;
2186: break;
2187: case ISP:
2188: tmpreg=0x804;
2189: break;
2190: #ifdef BUILTIN_MMUS
2191: case TC:
2192: tmpreg=0x003;
2193: break;
2194: case ITT0:
2195: tmpreg=0x004;
2196: break;
2197: case ITT1:
2198: tmpreg=0x005;
2199: break;
2200: case DTT0:
2201: tmpreg=0x006;
2202: break;
2203: case DTT1:
2204: tmpreg=0x007;
2205: break;
2206: case MMUSR:
2207: tmpreg=0x805;
2208: break;
2209: case URP:
2210: tmpreg=0x806;
2211: break;
2212: case SRP:
2213: tmpreg=0x807;
2214: break;
2215: #endif /* BUILTIN_MMUS */
2216: default:
2217: abort();
2218: }
2219: install_operand(s[1],tmpreg);
2220: break;
2221: #ifdef NeXT
2222: case '0':
2223: tmpreg=opP->reg-ADDR;
2224: install_operand(s[1],tmpreg);
2225: break;
2226: #endif /* NeXT */
2227:
2228: case 'k':
2229: tmpreg=get_num(opP->con1,55);
2230: install_operand(s[1],tmpreg&0x7f);
2231: break;
2232:
2233: case 'l':
2234: tmpreg=opP->reg;
2235: if(s[1]=='w') {
2236: if(tmpreg&0x7FF0000)
2237: as_bad("Floating point register in register list");
2238: insop(reverse_16_bits(tmpreg));
2239: } else {
2240: if(tmpreg&0x700FFFF)
2241: as_bad("Wrong register in floating-point reglist");
2242: install_operand(s[1],reverse_8_bits(tmpreg>>16));
2243: }
2244: break;
2245:
2246: case 'L':
2247: tmpreg=opP->reg;
2248: if(s[1]=='w') {
2249: if(tmpreg&0x7FF0000)
2250: as_bad("Floating point register in register list");
2251: insop(tmpreg);
2252: } else if(s[1]=='8') {
2253: if(tmpreg&0x0FFFFFF)
2254: as_bad("incorrect register in reglist");
2255: install_operand(s[1],tmpreg>>24);
2256: } else {
2257: if(tmpreg&0x700FFFF)
2258: as_bad("wrong register in floating-point reglist");
2259: else
2260: install_operand(s[1],tmpreg>>16);
2261: }
2262: break;
2263:
2264: case 'M':
2265: install_operand(s[1],get_num(opP->con1,60));
2266: break;
2267:
2268: case 'O':
2269: tmpreg= (opP->mode==DREG)
2270: ? 0x20+opP->reg-DATA
2271: : (get_num(opP->con1,40)&0x1F);
2272: install_operand(s[1],tmpreg);
2273: break;
2274:
2275: case 'Q':
2276: tmpreg=get_num(opP->con1,10);
2277: if(tmpreg==8)
2278: tmpreg=0;
2279: install_operand(s[1],tmpreg);
2280: break;
2281:
2282: case 'R':
2283: /* This depends on the fact that ADDR registers are
2284: eight more than their corresponding DATA regs, so
2285: the result will have the ADDR_REG bit set */
2286: install_operand(s[1],opP->reg-DATA);
2287: break;
2288:
2289: case 's':
2290: if(opP->reg==FPI) tmpreg=0x1;
2291: else if(opP->reg==FPS) tmpreg=0x2;
2292: else if(opP->reg==FPC) tmpreg=0x4;
2293: else abort();
2294: install_operand(s[1],tmpreg);
2295: break;
2296:
2297: case 'S': /* Ignore it */
2298: break;
2299:
2300: case 'T':
2301: install_operand(s[1],get_num(opP->con1,30));
2302: break;
2303:
2304: case 'U': /* Ignore it */
2305: break;
2306:
2307: #if defined(m68851) || defined(BUILTIN_MMUS)
2308: /* JF: These are out of order, I fear. */
2309: case 'f':
2310: switch (opP->reg) {
2311: case SFC:
2312: tmpreg=0;
2313: break;
2314: case DFC:
2315: tmpreg=1;
2316: break;
2317: default:
2318: abort();
2319: }
2320: install_operand(s[1],tmpreg);
2321: break;
2322: #endif
2323:
2324: #ifdef BUILTIN_MMUS
2325: case 'a':
2326: switch (opP->reg) {
2327: case SRP:
2328: tmpreg=2;
2329: break;
2330: case CRP:
2331: tmpreg=3;
2332: break;
2333: case TC:
2334: tmpreg=0;
2335: break;
2336: default:
2337: abort();
2338: }
2339: install_operand(s[1],tmpreg);
2340: break;
2341: case 'b':
2342: switch (opP->reg) {
2343: case MMUSR:
2344: tmpreg=0;
2345: break;
2346: default:
2347: abort();
2348: }
2349: install_operand(s[1],tmpreg);
2350: break;
2351: case 'c':
2352: switch (opP->reg) {
2353: case IC:
2354: tmpreg=2;
2355: break;
2356: case DC:
2357: tmpreg=1;
2358: break;
2359: case BC:
2360: tmpreg=3;
2361: break;
2362: default:
2363: abort();
2364: }
2365: install_operand(s[1],tmpreg);
2366: break;
2367: case 'e':
2368: switch (opP->reg) {
2369: case TT0:
2370: tmpreg=2;
2371: break;
2372: case TT1:
2373: tmpreg=3;
2374: break;
2375: default:
2376: abort();
2377: }
2378: install_operand(s[1],tmpreg);
2379: break;
2380: #endif
2381:
2382: #ifdef m68851
2383: case 'P':
2384: switch(opP->reg) {
2385: case TC:
2386: tmpreg=0;
2387: break;
2388: case CAL:
2389: tmpreg=4;
2390: break;
2391: case VAL:
2392: tmpreg=5;
2393: break;
2394: case SCC:
2395: tmpreg=6;
2396: break;
2397: case AC:
2398: tmpreg=7;
2399: break;
2400: default:
2401: abort();
2402: }
2403: install_operand(s[1],tmpreg);
2404: break;
2405:
2406: case 'V':
2407: if (opP->reg == VAL)
2408: break;
2409: abort();
2410:
2411: case 'W':
2412: switch(opP->reg) {
2413:
2414: case DRP:
2415: tmpreg=1;
2416: break;
2417: case SRP:
2418: tmpreg=2;
2419: break;
2420: case CRP:
2421: tmpreg=3;
2422: break;
2423: default:
2424: abort();
2425: }
2426: install_operand(s[1],tmpreg);
2427: break;
2428:
2429: case 'X':
2430: switch (opP->reg) {
2431: case BAD: case BAD+1: case BAD+2: case BAD+3:
2432: case BAD+4: case BAD+5: case BAD+6: case BAD+7:
2433: tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);
2434: break;
2435:
2436: case BAC: case BAC+1: case BAC+2: case BAC+3:
2437: case BAC+4: case BAC+5: case BAC+6: case BAC+7:
2438: tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);
2439: break;
2440:
2441: default:
2442: abort();
2443: }
2444: install_operand(s[1], tmpreg);
2445: break;
2446: case 'Y':
2447: if (opP->reg == PSR)
2448: break;
2449: abort();
2450:
2451: case 'Z':
2452: if (opP->reg == PCSR)
2453: break;
2454: abort();
2455: #endif /* m68851 */
2456: default:
2457: as_fatal("Internal error: Operand type %c unknown",s[0]);
2458: }
2459: }
2460: /* By the time whe get here (FINALLY) the_ins contains the complete
2461: instruction, ready to be emitted. . . */
2462: }
2463:
2464: static
2465: int
2466: get_regs(
2467: int i,
2468: struct m68k_op *opP,
2469: char *str)
2470: {
2471: /* 26, 25, 24, 23-16, 15-8, 0-7 */
2472: /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */
2473: unsigned long int cur_regs = 0;
2474: int reg1,
2475: reg2;
2476:
2477: #define ADD_REG(x) { if(x==FPI) cur_regs|=(1<<24);\
2478: else if(x==FPS) cur_regs|=(1<<25);\
2479: else if(x==FPC) cur_regs|=(1<<26);\
2480: else cur_regs|=(1<<(x-1)); }
2481:
2482: reg1=i;
2483: for(;;) {
2484: if(*str=='/') {
2485: ADD_REG(reg1);
2486: str++;
2487: } else if(*str=='-') {
2488: str++;
2489: reg2=m68k_reg_parse(&str);
2490: if(reg2<DATA || reg2>=FPREG+8 || reg1==FPI || reg1==FPS || reg1==FPC) {
2491: opP->error="unknown register in register list";
2492: return FAIL;
2493: }
2494: while(reg1<=reg2) {
2495: ADD_REG(reg1);
2496: reg1++;
2497: }
2498: if(*str=='\0')
2499: break;
2500: } else if(*str=='\0') {
2501: ADD_REG(reg1);
2502: break;
2503: } else {
2504: opP->error="unknow character in register list";
2505: return FAIL;
2506: }
2507: /* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */
2508: if (*str=='/')
2509: str ++;
2510: reg1=m68k_reg_parse(&str);
2511: if((reg1<DATA || reg1>=FPREG+8) && !(reg1==FPI || reg1==FPS || reg1==FPC)) {
2512: opP->error="unknown register in register list";
2513: return FAIL;
2514: }
2515: }
2516: opP->reg=cur_regs;
2517: return OK;
2518: }
2519:
2520: static
2521: int
2522: reverse_16_bits(
2523: int in)
2524: {
2525: int out=0;
2526: int n;
2527:
2528: static int mask[16] = {
2529: 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
2530: 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
2531: };
2532: for(n=0;n<16;n++) {
2533: if(in&mask[n])
2534: out|=mask[15-n];
2535: }
2536: return out;
2537: }
2538:
2539: static
2540: int
2541: reverse_8_bits(
2542: int in)
2543: {
2544: int out=0;
2545: int n;
2546:
2547: static int mask[8] = {
2548: 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
2549: };
2550:
2551: for(n=0;n<8;n++) {
2552: if(in&mask[n])
2553: out|=mask[7-n];
2554: }
2555: return out;
2556: }
2557:
2558: static
2559: void
2560: install_operand(
2561: int mode,
2562: int val)
2563: {
2564: switch(mode) {
2565: case 's':
2566: the_ins.opcode[0]|=val & 0xFF; /* JF FF is for M kludge */
2567: break;
2568: case 'd':
2569: the_ins.opcode[0]|=val<<9;
2570: break;
2571: case '1':
2572: the_ins.opcode[1]|=val<<12;
2573: break;
2574: case '2':
2575: the_ins.opcode[1]|=val<<6;
2576: break;
2577: case '3':
2578: the_ins.opcode[1]|=val;
2579: break;
2580: case '4':
2581: the_ins.opcode[2]|=val<<12;
2582: break;
2583: case '5':
2584: the_ins.opcode[2]|=val<<6;
2585: break;
2586: case '6':
2587: /* DANGER! This is a hack to force cas2l and cas2w cmds
2588: to be three words long! */
2589: the_ins.numo++;
2590: the_ins.opcode[2]|=val;
2591: break;
2592: case '7':
2593: the_ins.opcode[1]|=val<<7;
2594: break;
2595: case '8':
2596: the_ins.opcode[1]|=val<<10;
2597: break;
2598: #if defined(m68851) || defined(BUILTIN_MMUS)
2599: case '9':
2600: the_ins.opcode[1]|=val<<5;
2601: break;
2602: #endif
2603: #ifdef BUILTIN_MMUS
2604: case 'S':
2605: the_ins.opcode[0]|=val<<6;
2606: break;
2607: #endif
2608: case 't':
2609: the_ins.opcode[1]|=(val<<10)|(val<<7);
2610: break;
2611: case 'D':
2612: the_ins.opcode[1]|=(val<<12)|val;
2613: break;
2614: case 'g':
2615: the_ins.opcode[0]|=val=0xff;
2616: break;
2617: case 'i':
2618: the_ins.opcode[0]|=val<<9;
2619: break;
2620: case 'C':
2621: the_ins.opcode[1]|=val;
2622: break;
2623: case 'j':
2624: the_ins.opcode[1]|=val;
2625: the_ins.numo++; /* What a hack */
2626: break;
2627: case 'k':
2628: the_ins.opcode[1]|=val<<4;
2629: break;
2630: case 'b':
2631: case 'w':
2632: case 'l':
2633: break;
2634: case 'c':
2635: default:
2636: abort();
2637: }
2638: }
2639:
2640: static
2641: void
2642: install_gen_operand(
2643: int mode,
2644: int val)
2645: {
2646: switch(mode) {
2647: case 's':
2648: the_ins.opcode[0]|=val;
2649: break;
2650: case 'd':
2651: /* This is a kludge!!! */
2652: the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3;
2653: break;
2654: case 'b':
2655: case 'w':
2656: case 'l':
2657: case 'f':
2658: case 'F':
2659: case 'x':
2660: case 'p':
2661: the_ins.opcode[0]|=val;
2662: break;
2663: /* more stuff goes here */
2664: default:
2665: abort();
2666: }
2667: }
2668:
2669: static
2670: char *
2671: crack_operand(
2672: char *str,
2673: struct m68k_op *opP)
2674: {
2675: register int parens;
2676: register int c;
2677: register char *beg_str;
2678:
2679: if(!str) {
2680: return str;
2681: }
2682: beg_str=str;
2683: for(parens=0;*str && (parens>0 || notend(str));str++) {
2684: if(*str == '"') {
2685: str++;
2686: while(*str && *str != '"')
2687: str++;
2688: if(*str != '"'){ /* ERROR */
2689: opP->error="Missing \"";
2690: return str;
2691: }
2692: }
2693: else{
2694: if(*str=='(')
2695: parens++;
2696: else if(*str==')') {
2697: if(!parens) { /* ERROR */
2698: opP->error="Extra )";
2699: return str;
2700: }
2701: --parens;
2702: }
2703: }
2704: }
2705: if(!*str && parens) { /* ERROR */
2706: opP->error="Missing )";
2707: return str;
2708: }
2709: c= *str;
2710: *str='\0';
2711: if(m68k_ip_op(beg_str,opP)==FAIL) {
2712: *str=c;
2713: return str;
2714: }
2715: *str=c;
2716: if(c=='}')
2717: c= *++str; /* JF bitfield hack */
2718: if(c) {
2719: c= *++str;
2720: if(!c)
2721: as_bad("Missing operand");
2722: }
2723: return str;
2724: }
2725:
2726: /* See the comment up above where the #define notend(... is */
2727: #if 0
2728: notend(s)
2729: char *s;
2730: {
2731: if(*s==',') return 0;
2732: if(*s=='{' || *s=='}')
2733: return 0;
2734: if(*s!=':') return 1;
2735: /* This kludge here is for the division cmd, which is a kludge */
2736: if(index("aAdD#",s[1])) return 0;
2737: return 1;
2738: }
2739: #endif /* 0 */
2740:
2741: #ifdef NeXT
2742: static char *file_030, *file_040;
2743: static unsigned long line_030, line_040;
2744: #endif /* NeXT */
2745:
2746: /* This is the guts of the machine-dependent assembler. STR points to a
2747: machine dependent instruction. This funciton is supposed to emit
2748: the frags/bytes it assembles to.
2749: */
2750: void
2751: md_assemble(
2752: char *str)
2753: {
2754: char *er;
2755: short *fromP;
2756: char *toP = NULL;
2757: int m,n;
2758: char *to_beg_P;
2759: int shorts_this_frag;
2760:
2761: memset((char *)(&the_ins), '\0', sizeof(the_ins));
2762: m68_ip(str);
2763: er=the_ins.error;
2764: if(!er) {
2765: for(n=the_ins.numargs;n;--n)
2766: if(the_ins.operands[n].error) {
2767: er=the_ins.operands[n].error;
2768: break;
2769: }
2770: }
2771: if(er) {
2772: as_bad("\"%s\" -- Statement '%s' ignored",er,str);
2773: return;
2774: }
2775:
2776: #ifdef NeXT
2777: if(the_ins.cpus != NULL && !force_cpusubtype_ALL){
2778: if(md_cpusubtype == CPU_SUBTYPE_MC680x0_ALL){
2779: switch(*the_ins.cpus){
2780: case '2':
2781: as_bad("implementation specific instruction for the MC68020"
2782: " and -force_cpusubtype_ALL not specified");
2783: break;
2784: case '3':
2785: if(archflag_cpusubtype == CPU_SUBTYPE_MC68040)
2786: as_bad("030 instruction not allowed with -arch m68040");
2787: else{
2788: file_030 = logical_input_file ?
2789: logical_input_file : physical_input_file;
2790: line_030 = logical_input_line ?
2791: logical_input_line : physical_input_line;
2792: md_cpusubtype = CPU_SUBTYPE_MC68030_ONLY;
2793: }
2794: break;
2795: case '4':
2796: if(archflag_cpusubtype == CPU_SUBTYPE_MC68030_ONLY)
2797: as_bad("040 instruction not allowed with -arch m68030");
2798: else{
2799: file_040 = logical_input_file ?
2800: logical_input_file : physical_input_file;
2801: line_040 = logical_input_line ?
2802: logical_input_line : physical_input_line;
2803: md_cpusubtype = CPU_SUBTYPE_MC68040;
2804: }
2805: break;
2806: }
2807: }
2808: else{
2809: switch(*the_ins.cpus){
2810: case '2':
2811: as_bad("implementation specific instruction for the MC68020"
2812: " and -force_cpusubtype_ALL not specified");
2813: break;
2814: case '3':
2815: if(archflag_cpusubtype == CPU_SUBTYPE_MC68040)
2816: as_bad("030 instruction not allowed with -arch m68040");
2817: else{
2818: if(md_cpusubtype != CPU_SUBTYPE_MC680x0_ALL &&
2819: md_cpusubtype != CPU_SUBTYPE_MC68030_ONLY)
2820: as_bad("more than one implementation specific "
2821: "instruction seen and -force_cpusubtype_ALL "
2822: " not specified (first 040 instruction in: "
2823: "%s at line %lu)", file_040, line_040);
2824: md_cpusubtype = CPU_SUBTYPE_MC68030_ONLY;
2825: }
2826: break;
2827: case '4':
2828: if(archflag_cpusubtype == CPU_SUBTYPE_MC68030_ONLY)
2829: as_bad("040 instruction not allowed with -arch m68030");
2830: else{
2831: if(md_cpusubtype != CPU_SUBTYPE_MC680x0_ALL &&
2832: md_cpusubtype != CPU_SUBTYPE_MC68040)
2833: as_bad("more than one implementation specific "
2834: "instruction seen and -force_cpusubtype_ALL "
2835: "not specified (first 030 instruction in: "
2836: "%s at line %lu)", file_030, line_030);
2837: md_cpusubtype = CPU_SUBTYPE_MC68040;
2838: }
2839: break;
2840: }
2841: }
2842: }
2843: #endif /* NeXT */
2844:
2845: #ifdef NeXT /* generate stabs for debugging assembly code */
2846: /*
2847: * If the -g flag is present generate a line number stab for the
2848: * instruction.
2849: *
2850: * See the detailed comments about stabs in read_a_source_file() for a
2851: * description of what is going on here.
2852: */
2853: if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
2854: (void)symbol_new(
2855: "",
2856: 68 /* N_SLINE */,
2857: text_nsect,
2858: logical_input_line /* n_desc, line number */,
2859: obstack_next_free(&frags) - frag_now->fr_literal,
2860: frag_now);
2861: }
2862: #endif /* NeXT */
2863:
2864: if(the_ins.nfrag==0) { /* No frag hacking involved; just put it out */
2865: toP=frag_more(2*the_ins.numo);
2866: fromP= &the_ins.opcode[0];
2867: for(m=the_ins.numo;m;--m) {
2868: md_number_to_chars(toP,(long)(*fromP),2);
2869: toP+=2;
2870: fromP++;
2871: }
2872: /* put out symbol-dependent info */
2873: for(m=0;m<the_ins.nrel;m++) {
2874: switch(the_ins.reloc[m].wid) {
2875: case 'B':
2876: n=1;
2877: break;
2878: case 'b':
2879: n=1;
2880: break;
2881: case '3':
2882: #ifdef NeXT
2883: /* This is a bug fix that is not in the 1.36
2884: * version of GAS for this construct:
2885: * fmovemx #foo,a0@-
2886: * foo = 0xffff;
2887: * Where the width of the relocation should be
2888: * one byte (the low 8 bits of the second word)
2889: * for the floating point register mask. Other- * wise the next byte after this instruction
2890: * gets trashed by this relocation.
2891: */
2892: n=1;
2893: #else /* !defined(NeXT) */
2894: n=2;
2895: #endif /* NeXT */
2896: break;
2897: case 'w':
2898: n=2;
2899: break;
2900: case 'l':
2901: n=4;
2902: break;
2903: default:
2904: as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid);
2905: }
2906:
2907: fix_new(frag_now,
2908: (toP - frag_now->fr_literal) -
2909: the_ins.numo * 2 + the_ins.reloc[m].n,
2910: n,
2911: the_ins.reloc[m].add,
2912: the_ins.reloc[m].sub,
2913: the_ins.reloc[m].off,
2914: the_ins.reloc[m].pcrel,
2915: 0,0);
2916: }
2917: return;
2918: }
2919:
2920: /* There's some frag hacking */
2921: for(n=0,fromP= &the_ins.opcode[0];n<the_ins.nfrag;n++) {
2922: int wid;
2923:
2924: if(n==0) wid=2*the_ins.fragb[n].fragoff;
2925: else wid=2*(the_ins.numo-the_ins.fragb[n-1].fragoff);
2926: toP=frag_more(wid);
2927: to_beg_P=toP;
2928: shorts_this_frag=0;
2929: for(m=wid/2;m;--m) {
2930: md_number_to_chars(toP,(long)(*fromP),2);
2931: toP+=2;
2932: fromP++;
2933: shorts_this_frag++;
2934: }
2935: for(m=0;m<the_ins.nrel;m++) {
2936: if((the_ins.reloc[m].n)>= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */) {
2937: the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */;
2938: break;
2939: }
2940: wid=the_ins.reloc[m].wid;
2941: if(wid==0)
2942: continue;
2943: the_ins.reloc[m].wid=0;
2944: wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000;
2945:
2946: fix_new(frag_now,
2947: (toP - frag_now->fr_literal) -
2948: the_ins.numo * 2 + the_ins.reloc[m].n,
2949: wid,
2950: the_ins.reloc[m].add,
2951: the_ins.reloc[m].sub,
2952: the_ins.reloc[m].off,
2953: the_ins.reloc[m].pcrel,
2954: 0,0);
2955: }
2956: know(the_ins.fragb[n].fadd);
2957: (void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty),
2958: the_ins.fragb[n].fadd,the_ins.fragb[n].foff,to_beg_P);
2959: }
2960: n=(the_ins.numo-the_ins.fragb[n-1].fragoff);
2961: shorts_this_frag=0;
2962: if(n) {
2963: toP=frag_more(n*sizeof(short));
2964: while(n--) {
2965: md_number_to_chars(toP,(long)(*fromP),2);
2966: toP+=2;
2967: fromP++;
2968: shorts_this_frag++;
2969: }
2970: }
2971: for(m=0;m<the_ins.nrel;m++) {
2972: int wid;
2973:
2974: wid=the_ins.reloc[m].wid;
2975: if(wid==0)
2976: continue;
2977: the_ins.reloc[m].wid=0;
2978: wid = (wid=='b') ? 1 : (wid=='w') ? 2 : (wid=='l') ? 4 : 4000;
2979:
2980: fix_new(frag_now,
2981: (the_ins.reloc[m].n + toP-frag_now->fr_literal) -
2982: /* the_ins.numo */ shorts_this_frag * 2,
2983: wid,
2984: the_ins.reloc[m].add,
2985: the_ins.reloc[m].sub,
2986: the_ins.reloc[m].off,
2987: the_ins.reloc[m].pcrel,
2988: 0,0);
2989: }
2990: }
2991:
2992: /* This function is called once, at assembler startup time. This should
2993: set up all the tables, etc that the MD part of the assembler needs
2994: */
2995: void
2996: md_begin(
2997: void)
2998: {
2999: /*
3000: * md_begin -- set up hash tables with 68000 instructions.
3001: * similar to what the vax assembler does. ---phr
3002: */
3003: /* RMS claims the thing to do is take the m68k-opcode.h table, and make
3004: a copy of it at runtime, adding in the information we want but isn't
3005: there. I think it'd be better to have an awk script hack the table
3006: at compile time. Or even just xstr the table and use it as-is. But
3007: my lord ghod hath spoken, so we do it this way. Excuse the ugly var
3008: names. */
3009:
3010: register struct m68k_opcode *ins;
3011: register struct m68_incant *hack,
3012: *slak;
3013: register char *retval = 0; /* empty string, or error msg text */
3014: register int i;
3015: register char c;
3016:
3017: if ((op_hash = hash_new()) == NULL)
3018: as_fatal("Virtual memory exhausted");
3019:
3020: obstack_begin(&robyn,4000);
3021: for (ins = (struct m68k_opcode *)m68k_opcodes; ins < endop; ins++) {
3022: hack=slak=(struct m68_incant *)obstack_alloc(&robyn,sizeof(struct m68_incant));
3023: do {
3024: slak->m_operands=ins->args;
3025: slak->m_opnum=strlen(slak->m_operands)/2;
3026: slak->m_opcode=ins->opcode;
3027: /* This is kludgey */
3028: slak->m_codenum=((ins->match)&0xffffL) ? 2 : 1;
3029: #ifdef NeXT
3030: slak->m_cpus = ins->cpus;
3031: #endif /* NeXT */
3032: if((ins+1)!=endop && !strcmp(ins->name,(ins+1)->name)) {
3033: slak->m_next=(struct m68_incant *)
3034: obstack_alloc(&robyn,sizeof(struct m68_incant));
3035: ins++;
3036: } else
3037: slak->m_next=0;
3038: slak=slak->m_next;
3039: } while(slak);
3040:
3041: retval = hash_insert (op_hash, ins->name,(char *)hack);
3042: /* Didn't his mommy tell him about null pointers? */
3043: if(retval && *retval)
3044: as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval);
3045: }
3046:
3047: for (i = 0; i < sizeof(mklower_table) ; i++)
3048: mklower_table[i] = (isupper(c = (char) i)) ? tolower(c) : c;
3049:
3050: for (i = 0 ; i < sizeof(notend_table) ; i++) {
3051: notend_table[i] = 0;
3052: alt_notend_table[i] = 0;
3053: }
3054: notend_table[','] = 1;
3055: notend_table['{'] = 1;
3056: notend_table['}'] = 1;
3057: alt_notend_table['a'] = 1;
3058: alt_notend_table['A'] = 1;
3059: alt_notend_table['d'] = 1;
3060: alt_notend_table['D'] = 1;
3061: alt_notend_table['#'] = 1;
3062: alt_notend_table['f'] = 1;
3063: alt_notend_table['F'] = 1;
3064: }
3065:
3066: #if 0
3067: #define notend(s) ((*s == ',' || *s == '}' || *s == '{' \
3068: || (*s == ':' && index("aAdD#", s[1]))) \
3069: ? 0 : 1)
3070: #endif
3071:
3072: /* This funciton is called once, before the assembler exits. It is
3073: supposed to do any final cleanup for this part of the assembler.
3074: */
3075: void
3076: md_end(
3077: void)
3078: {
3079: }
3080:
3081: /* Equal to MAX_PRECISION in atof-ieee.c */
3082: #define MAX_LITTLENUMS 6
3083:
3084: /* Turn a string in input_line_pointer into a floating point constant of type
3085: type, and store the appropriate bytes in *litP. The number of LITTLENUMS
3086: emitted is stored in *sizeP . An error message is returned, or NULL on OK.
3087: */
3088: char *
3089: md_atof(
3090: int type,
3091: char *litP,
3092: int *sizeP)
3093: {
3094: int prec;
3095: LITTLENUM_TYPE words[MAX_LITTLENUMS];
3096: LITTLENUM_TYPE *wordP;
3097: char *t;
3098:
3099: switch(type) {
3100: case 'f':
3101: case 'F':
3102: case 's':
3103: case 'S':
3104: prec = 2;
3105: break;
3106:
3107: case 'd':
3108: case 'D':
3109: case 'r':
3110: case 'R':
3111: prec = 4;
3112: break;
3113:
3114: case 'x':
3115: case 'X':
3116: prec = 6;
3117: break;
3118:
3119: case 'p':
3120: case 'P':
3121: prec = 6;
3122: break;
3123:
3124: default:
3125: *sizeP=0;
3126: return "Bad call to MD_ATOF()";
3127: }
3128: t=atof_ieee(input_line_pointer,type,words);
3129: if(t)
3130: input_line_pointer=t;
3131:
3132: *sizeP=prec * sizeof(LITTLENUM_TYPE);
3133: for(wordP=words;prec--;) {
3134: md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
3135: litP+=sizeof(LITTLENUM_TYPE);
3136: }
3137: return ""; /* Someone should teach Dean about null pointers */
3138: }
3139:
3140: /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
3141: for use in the a.out file, and stores them in the array pointed to by buf.
3142: This knows about the endian-ness of the target machine and does
3143: THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
3144: 2 (short) and 4 (long) Floating numbers are put out as a series of
3145: LITTLENUMS (shorts, here at least)
3146: */
3147: void
3148: md_number_to_chars(
3149: char *buf,
3150: long val,
3151: int n)
3152: {
3153: switch(n) {
3154: case 1:
3155: *buf++=val;
3156: break;
3157: case 2:
3158: *buf++=(val>>8);
3159: *buf++=val;
3160: break;
3161: case 4:
3162: *buf++=(val>>24);
3163: *buf++=(val>>16);
3164: *buf++=(val>>8);
3165: *buf++=val;
3166: break;
3167: default:
3168: abort();
3169: }
3170: }
3171:
3172: void
3173: md_number_to_imm(
3174: unsigned char *buf,
3175: long val,
3176: int n,
3177: fixS *fixP,
3178: int nsect)
3179: {
3180: switch(n) {
3181: case 1:
3182: *buf++=val;
3183: break;
3184: case 2:
3185: *buf++=(val>>8);
3186: *buf++=val;
3187: break;
3188: case 4:
3189: *buf++=(val>>24);
3190: *buf++=(val>>16);
3191: *buf++=(val>>8);
3192: *buf++=val;
3193: break;
3194: default:
3195: abort();
3196: }
3197: }
3198:
3199: /*
3200: * Force truly undefined symbols to their maximum size, and generally set up
3201: * the frag list to be relaxed. It is the caller's responsiblity to set the
3202: * current section, frchain_now, to the corresponding nsect specified so that
3203: * calls to fix_new() will make fixes for this section.
3204: */
3205: int
3206: md_estimate_size_before_relax(
3207: fragS *fragP,
3208: int nsect)
3209: {
3210: int old_fix;
3211:
3212: old_fix = fragP->fr_fix;
3213:
3214: /*
3215: * Handle SZ_UNDEF first, it can be changed to BYTE or SHORT.
3216: */
3217: switch(fragP->fr_subtype){
3218: case TAB(DBCC, SZ_UNDEF):
3219: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){
3220: fragP->fr_subtype = TAB(DBCC, SHORT);
3221: fragP->fr_var += 2;
3222: break;
3223: }
3224: /*
3225: * Only DBcc 68000 instructions can come here.
3226: * Change dbcc into dbcc/jmp absl long.
3227: */
3228: fragP->fr_opcode[2] = 0x00; /* branch offset = 4 */
3229: fragP->fr_opcode[3] = 0x04;
3230: fragP->fr_opcode[4] = 0x60; /* put in bra pc+6 */
3231: fragP->fr_opcode[5] = 0x06;
3232: fragP->fr_opcode[6] = 0x4e; /* put in jmp long (0x4ef9) */
3233: fragP->fr_opcode[7] = 0xf9;
3234: fragP->fr_fix += 6; /* account for bra/jmp instructions */
3235: fix_new(fragP,
3236: fragP->fr_fix,
3237: 4,
3238: fragP->fr_symbol,
3239: 0,
3240: fragP->fr_offset,
3241: 0,
3242: 0,
3243: 0);
3244: fragP->fr_fix += 4; /* account for jmp instruction displacement */
3245: frag_wane(fragP);
3246: break;
3247:
3248: case TAB(BCC68000, SZ_UNDEF):
3249: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){
3250: fragP->fr_subtype = TAB(BCC68000, BYTE);
3251: break;
3252: }
3253: /*
3254: * Only Bcc 68000 instructions can come here.
3255: * Change bcc into b!cc/jmp absl long.
3256: */
3257: fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
3258: fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */
3259: fragP->fr_opcode[2] = 0x4e; /* put in jmp long (0x4ef9) */
3260: fragP->fr_opcode[3] = 0xf9;
3261: fragP->fr_fix += 2; /* account for jmp instruction */
3262: fix_new(fragP,
3263: fragP->fr_fix,
3264: 4,
3265: fragP->fr_symbol,
3266: 0,
3267: fragP->fr_offset,
3268: 0,
3269: 0,
3270: 0);
3271: fragP->fr_fix += 4; /* account for jmp instruction displacement */
3272: frag_wane(fragP);
3273: break;
3274:
3275: case TAB(BRANCH, SZ_UNDEF):
3276: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){
3277: /*
3278: * The NeXT linker has the ability to scatter blocks of
3279: * sections between labels. This requires that brances to
3280: * labels that survive to the link phase must be able to
3281: * be relocated.
3282: */
3283: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']){
3284: fix_new(fragP,
3285: fragP->fr_fix,
3286: 4,
3287: fragP->fr_symbol,
3288: 0,
3289: fragP->fr_offset + 4,
3290: 1,
3291: 1,
3292: 0);
3293: fragP->fr_fix += 4;
3294: fragP->fr_opcode[1] = 0xff;
3295: frag_wane(fragP);
3296: break;
3297: }
3298: else
3299: fragP->fr_subtype = TAB(BRANCH, BYTE);
3300: break;
3301: }
3302: else if(flagseen['m']){
3303: if(fragP->fr_opcode[0] == 0x61){
3304: fragP->fr_opcode[0] = 0x4E;
3305: fragP->fr_opcode[1] = 0xB9; /* JBSR with ABSL LONG offset */
3306: fix_new(fragP,
3307: fragP->fr_fix,
3308: 4,
3309: fragP->fr_symbol,
3310: 0,
3311: fragP->fr_offset,
3312: 0,
3313: 0,
3314: 0);
3315: fragP->fr_fix += 4;
3316: frag_wane(fragP);
3317: }
3318: else if(fragP->fr_opcode[0] == 0x60){
3319: fragP->fr_opcode[0] = 0x4E;
3320: fragP->fr_opcode[1] = 0xF9; /* JMP with ABSL LONG offset */
3321: fix_new(fragP,
3322: fragP->fr_fix,
3323: 4,
3324: fragP->fr_symbol,
3325: 0,
3326: fragP->fr_offset,
3327: 0,
3328: 0,
3329: 0);
3330: fragP->fr_fix += 4;
3331: frag_wane(fragP);
3332: }
3333: else{
3334: as_warn("Long branch offset to extern symbol not "
3335: "supported.");
3336: }
3337: break;
3338: }
3339: else{
3340: /* Symbol is still undefined. Make it simple */
3341: fix_new(fragP,
3342: fragP->fr_fix,
3343: 4,
3344: fragP->fr_symbol,
3345: 0,
3346: fragP->fr_offset + 4,
3347: 1,
3348: 1,
3349: 0);
3350: fragP->fr_fix += 4;
3351: fragP->fr_opcode[1] = 0xff;
3352: frag_wane(fragP);
3353: break;
3354: }
3355: break;
3356:
3357: case TAB(FBRANCH, SZ_UNDEF):
3358: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){
3359: /*
3360: * The NeXT linker has the ability to scatter blocks of
3361: * sections between labels. This requires that brances to
3362: * labels that survive to the link phase must be able to
3363: * be relocated.
3364: */
3365: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']) {
3366: fix_new(fragP,
3367: fragP->fr_fix,
3368: 4,
3369: fragP->fr_symbol,
3370: 0,
3371: fragP->fr_offset + 4,
3372: 1,
3373: 1,
3374: 0);
3375: fragP->fr_fix += 4;
3376: fragP->fr_opcode[1] |= 0x40;
3377: frag_wane(fragP);
3378: break;
3379: }
3380: else{
3381: fragP->fr_subtype = TAB(FBRANCH, SHORT);
3382: fragP->fr_var += 2;
3383: }
3384: }
3385: else {
3386: /* Symbol is still undefined. Make it long */
3387: fix_new(fragP,
3388: fragP->fr_fix,
3389: 4,
3390: fragP->fr_symbol,
3391: 0,
3392: fragP->fr_offset + 4,
3393: 1,
3394: 1,
3395: 0);
3396: fragP->fr_fix += 4;
3397: fragP->fr_opcode[1] |= 0x40;
3398: frag_wane(fragP);
3399: break;
3400: }
3401: break;
3402:
3403: case TAB(PCREL, SZ_UNDEF):
3404: if(fragP->fr_symbol->sy_nlist.n_sect == nsect){
3405: /*
3406: * The NeXT linker has the ability to scatter blocks of
3407: * sections between labels. This requires that brances to
3408: * labels that survive to the link phase must be able to
3409: * be relocated.
3410: */
3411: if(fragP->fr_symbol->sy_name[0] != 'L' || flagseen ['L']) {
3412: /*
3413: * The thing to do here is force it to ABSOLUTE LONG, since
3414: * PCREL is really trying to shorten an ABSOLUTE address
3415: * anyway.
3416: */
3417: if((fragP->fr_opcode[1] & 0x3F) != 0x3A)
3418: as_bad("Internal error (long PC-relative operand) for "
3419: "insn 0x%04x at 0x%lx", fragP->fr_opcode[0],
3420: fragP->fr_address);
3421: fragP->fr_opcode[1] &= ~0x3F;
3422: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */
3423: fix_new(fragP,
3424: fragP->fr_fix,
3425: 4,
3426: fragP->fr_symbol,
3427: 0,
3428: fragP->fr_offset,
3429: 0,
3430: 0,
3431: 0);
3432: fragP->fr_fix += 4;
3433: frag_wane(fragP);
3434: }
3435: else{
3436: fragP->fr_subtype = TAB(PCREL, SHORT);
3437: fragP->fr_var += 2;
3438: }
3439: }
3440: else {
3441: /* Symbol is still undefined. Make it long */
3442: if((fragP->fr_opcode[1] & 0x3F) != 0x3A)
3443: as_bad("Internal error (long PC-relative operand) for "
3444: "insn 0x%04x at 0x%lx", fragP->fr_opcode[0],
3445: fragP->fr_address);
3446: fragP->fr_opcode[1] &= ~0x3F;
3447: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */
3448: fix_new(fragP,
3449: fragP->fr_fix,
3450: 4,
3451: fragP->fr_symbol,
3452: 0,
3453: fragP->fr_offset,
3454: 1,
3455: 1,
3456: 0);
3457: fragP->fr_fix += 4;
3458: frag_wane(fragP);
3459: break;
3460: }
3461: break;
3462:
3463: default:
3464: break;
3465: }
3466:
3467: /*
3468: * Now that SZ_UNDEF are taken care of, check others
3469: */
3470: switch(fragP->fr_subtype) {
3471: case TAB(BCC68000, BYTE):
3472: case TAB(BRANCH, BYTE):
3473: /*
3474: * We can't do a short jump to the next instruction,
3475: * so we force word mode.
3476: */
3477: if(fragP->fr_symbol != NULL &&
3478: fragP->fr_symbol->sy_value == 0 &&
3479: fragP->fr_symbol->sy_frag == fragP->fr_next) {
3480: fragP->fr_subtype = TAB(TABTYPE(fragP->fr_subtype), SHORT);
3481: fragP->fr_var += 2;
3482: }
3483: break;
3484: default:
3485: break;
3486: }
3487: return(fragP->fr_var + fragP->fr_fix - old_fix);
3488: }
3489:
3490: /*
3491: * *fragP has been relaxed to its final size, and now needs to have
3492: * the bytes inside it modified to conform to the new size. There is UGLY
3493: * MAGIC here interms of changing the addressing mode of some instructions
3494: * and using other instructions in place of the original in the case of the
3495: * 68000 and 68010 where long pc-relative forms don't exist.
3496: */
3497: void
3498: md_convert_frag(
3499: fragS *fragP)
3500: {
3501: long disp;
3502: long ext;
3503: char *buffer_address;
3504: int object_address;
3505:
3506: ext = 0;
3507:
3508: /* Address in gas core of the place to store the displacement. */
3509: buffer_address = fragP->fr_fix + fragP->fr_literal;
3510:
3511: /* Address in object code of the displacement. */
3512: object_address = fragP->fr_fix + fragP->fr_address;
3513:
3514: know(fragP->fr_symbol);
3515:
3516: /* The displacement of the address, from current location. */
3517: disp = (fragP->fr_symbol->sy_value + fragP->fr_offset) - object_address;
3518:
3519: switch(fragP->fr_subtype){
3520: case TAB(BCC68000, BYTE):
3521: case TAB(BRANCH, BYTE):
3522: know(issbyte(disp));
3523: if(disp == 0){
3524: /* Replace this with a nop. */
3525: fragP->fr_opcode[0] = 0x4e;
3526: fragP->fr_opcode[1] = 0x71;
3527: }
3528: else{
3529: fragP->fr_opcode[1] = disp;
3530: }
3531: ext = 0;
3532: break;
3533:
3534: case TAB(DBCC, SHORT):
3535: know(issword(disp));
3536: ext=2;
3537: break;
3538:
3539: case TAB(BCC68000, SHORT):
3540: case TAB(BRANCH, SHORT):
3541: know(issword(disp));
3542: fragP->fr_opcode[1] = 0x00;
3543: ext = 2;
3544: break;
3545:
3546: case TAB(BRANCH,LONG):
3547: if(flagseen['m']){
3548: if(fragP->fr_opcode[0] == 0x61){
3549: fragP->fr_opcode[0] = 0x4E;
3550: fragP->fr_opcode[1] = 0xB9; /* JBSR with ABSL LONG offset */
3551: fix_new(fragP,
3552: fragP->fr_fix,
3553: 4,
3554: fragP->fr_symbol,
3555: 0,
3556: fragP->fr_offset,
3557: 0,
3558: 0,
3559: 0);
3560: fragP->fr_fix += 4;
3561: ext = 0;
3562: }
3563: else if(fragP->fr_opcode[0] == 0x60){
3564: fragP->fr_opcode[0]= 0x4E;
3565: fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */
3566: fix_new(fragP,
3567: fragP->fr_fix,
3568: 4,
3569: fragP->fr_symbol,
3570: 0,
3571: fragP->fr_offset,
3572: 0,
3573: 0,
3574: 0);
3575: fragP->fr_fix += 4;
3576: ext = 0;
3577: }
3578: else{
3579: as_bad("Long branch offset not supported.");
3580: }
3581: }
3582: else{
3583: fragP->fr_opcode[1] = 0xff;
3584: ext = 4;
3585: }
3586: break;
3587:
3588: case TAB(BCC68000, LONG):
3589: /*
3590: * Only Bcc 68000 instructions can come here.
3591: * Change bcc into b!cc/jmp absl long.
3592: */
3593: fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
3594: fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */
3595: fragP->fr_opcode[2] = 0x4e; /* put in jmp long (0x4ef9) */
3596: fragP->fr_opcode[3] = 0xf9;
3597: fragP->fr_fix += 2; /* account for jmp instruction */
3598: fix_new(fragP,
3599: fragP->fr_fix,
3600: 4,
3601: fragP->fr_symbol,
3602: 0,
3603: fragP->fr_offset,
3604: 0,
3605: 0,
3606: 0);
3607: fragP->fr_fix += 4; /* account for jmp instruction's displacement */
3608: ext = 0;
3609: break;
3610:
3611: case TAB(DBCC, LONG):
3612: /*
3613: * Only DBcc 68000 instructions can come here.
3614: * Change dbcc into dbcc/jmp absl long.
3615: */
3616: fragP->fr_opcode[2] = 0x00; /* branch offset = 4 */
3617: fragP->fr_opcode[3] = 0x04;
3618: fragP->fr_opcode[4] = 0x60; /* put in bra pc+6 */
3619: fragP->fr_opcode[5] = 0x06;
3620: fragP->fr_opcode[6] = 0x4e; /* put in jmp long (0x4ef9) */
3621: fragP->fr_opcode[7] = 0xf9;
3622: fragP->fr_fix += 6; /* account for bra/jmp instructions */
3623: fix_new(fragP,
3624: fragP->fr_fix,
3625: 4,
3626: fragP->fr_symbol,
3627: 0,
3628: fragP->fr_offset,
3629: 0,
3630: 0,
3631: 0);
3632: fragP->fr_fix += 4; /* account for jmp instruction's displacement */
3633: ext = 0;
3634: break;
3635:
3636: case TAB(FBRANCH, SHORT):
3637: know((fragP->fr_opcode[1] & 0x40) == 0);
3638: ext = 2;
3639: break;
3640:
3641: case TAB(FBRANCH, LONG):
3642: fragP->fr_opcode[1] |= 0x40; /* Turn on LONG bit */
3643: ext = 4;
3644: break;
3645:
3646: case TAB(PCREL,SHORT):
3647: ext = 2;
3648: break;
3649:
3650: case TAB(PCREL,LONG):
3651: /*
3652: * The thing to do here is force it to ABSOLUTE LONG, since
3653: * PCREL is really trying to shorten an ABSOLUTE address anyway.
3654: */
3655: if((fragP->fr_opcode[1] & 0x3F) != 0x3A)
3656: as_bad("Internal error (long PC-relative operand) for insn "
3657: "0x%04x at 0x%lx", fragP->fr_opcode[0],
3658: fragP->fr_address);
3659: fragP->fr_opcode[1] &= ~0x3F;
3660: fragP->fr_opcode[1] |= 0x39; /* Mode 7.1 */
3661: fix_new(fragP,
3662: fragP->fr_fix,
3663: 4,
3664: fragP->fr_symbol,
3665: 0,
3666: fragP->fr_offset,
3667: 0,
3668: 0,
3669: 0);
3670: fragP->fr_fix += 4; /* account for the instruction's displacement */
3671: ext = 0;
3672: break;
3673:
3674: default:
3675: break;
3676: }
3677:
3678: if(ext != 0){
3679: md_number_to_chars(buffer_address, (long)disp, (int)ext);
3680: fragP->fr_fix += ext;
3681: }
3682: }
3683:
3684: /* Different values of OK tell what its OK to return. Things that aren't OK are an error (what a shock, no?)
3685:
3686: 0: Everything is OK
3687: 10: Absolute 1:8 only
3688: 20: Absolute 0:7 only
3689: 30: absolute 0:15 only
3690: 40: Absolute 0:31 only
3691: 50: absolute 0:127 only
3692: 55: absolute -64:63 only
3693: 60: absolute -128:127 only
3694: 70: absolute 0:4095 only
3695: 80: No bignums
3696:
3697: */
3698: static
3699: int
3700: get_num(
3701: struct m68k_exp *exp,
3702: int ok)
3703: {
3704: #ifdef TEST2
3705: long l = 0;
3706:
3707: if(!exp->e_beg)
3708: return 0;
3709: if(*exp->e_beg=='0') {
3710: if(exp->e_beg[1]=='x')
3711: sscanf(exp->e_beg+2,"%x",&l);
3712: else
3713: sscanf(exp->e_beg+1,"%O",&l);
3714: return l;
3715: }
3716: return atol(exp->e_beg);
3717: #else /* !defined(TEST2) */
3718: char *save_in;
3719: char c_save;
3720:
3721: if(!exp) {
3722: /* Can't do anything */
3723: return 0;
3724: }
3725: if(!exp->e_beg || !exp->e_end) {
3726: seg(exp)=SEG_ABSOLUTE;
3727: adds(exp)=0;
3728: subs(exp)=0;
3729: offs(exp)= (ok==10) ? 1 : 0;
3730: as_warn("Null expression defaults to %ld",offs(exp));
3731: return 0;
3732: }
3733:
3734: exp->e_siz=0;
3735: if(/* ok!=80 && */exp->e_end[-1]==':' && (exp->e_end-exp->e_beg)>=2) {
3736: switch(exp->e_end[0]) {
3737: case 's':
3738: case 'b':
3739: exp->e_siz=1;
3740: break;
3741: case 'w':
3742: exp->e_siz=2;
3743: break;
3744: case 'l':
3745: exp->e_siz=3;
3746: break;
3747: default:
3748: as_bad("Unknown size for expression \"%c\"",exp->e_end[0]);
3749: }
3750: exp->e_end-=2;
3751: }
3752: c_save=exp->e_end[1];
3753: exp->e_end[1]='\0';
3754: save_in=input_line_pointer;
3755: input_line_pointer=exp->e_beg;
3756: #ifdef NeXT /* feature to try to make expressions absolute */
3757: (void) expression (&(exp->e_exp));
3758: /* DJA -- we will try to make an absolute number here */
3759: switch(try_to_make_absolute(&(exp->e_exp))) {
3760: #else /* !defined(NeXT) */
3761: switch(expression(&(exp->e_exp))) {
3762: #endif /* NeXT */
3763: case SEG_NONE:
3764: /* Do the same thing the VAX asm does */
3765: seg(exp)=SEG_ABSOLUTE;
3766: adds(exp)=0;
3767: subs(exp)=0;
3768: offs(exp)=0;
3769: if(ok==10) {
3770: as_warn("expression out of range: defaulting to 1");
3771: offs(exp)=1;
3772: }
3773: break;
3774: case SEG_ABSOLUTE:
3775: switch(ok) {
3776: case 10:
3777: if(offs(exp)<1 || offs(exp)>8) {
3778: as_warn("expression out of range: defaulting to 1");
3779: offs(exp)=1;
3780: }
3781: break;
3782: case 20:
3783: if(offs(exp)<0 || offs(exp)>7)
3784: goto outrange;
3785: break;
3786: case 30:
3787: if(offs(exp)<0 || offs(exp)>15)
3788: goto outrange;
3789: break;
3790: case 40:
3791: if(offs(exp)<0 || offs(exp)>32)
3792: goto outrange;
3793: break;
3794: case 50:
3795: if(offs(exp)<0 || offs(exp)>127)
3796: goto outrange;
3797: break;
3798: case 55:
3799: if(offs(exp)<-64 || offs(exp)>63)
3800: goto outrange;
3801: break;
3802: case 60:
3803: if(offs(exp)<-128 || offs(exp)>127)
3804: goto outrange;
3805: break;
3806: case 70:
3807: if(offs(exp)<0 || offs(exp)>4095) {
3808: outrange:
3809: as_warn("expression out of range: defaulting to 0");
3810: offs(exp)=0;
3811: }
3812: break;
3813: default:
3814: break;
3815: }
3816: break;
3817: case SEG_SECT:
3818: case SEG_UNKNOWN:
3819: case SEG_DIFFSECT:
3820: if(ok>=10 && ok<=70) {
3821: seg(exp)=SEG_ABSOLUTE;
3822: adds(exp)=0;
3823: subs(exp)=0;
3824: offs(exp)= (ok==10) ? 1 : 0;
3825: as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
3826: }
3827: break;
3828: case SEG_BIG:
3829: #ifndef NeXT /* fix for bug #8331 */ /* This hack is already done by expr */
3830: if(ok==80 && offs(exp)<0) { /* HACK! Turn it into a long */
3831: LITTLENUM_TYPE words[6];
3832:
3833: gen_to_words(words,2,8L);/* These numbers are magic! */
3834: seg(exp)=SEG_ABSOLUTE;
3835: adds(exp)=0;
3836: subs(exp)=0;
3837: offs(exp)=words[1]|(words[0]<<16);
3838: } else if(ok!=0) {
3839: #else /* defined(NeXT) */
3840: if(ok!=0) {
3841: #endif /* NeXT */
3842: seg(exp)=SEG_ABSOLUTE;
3843: adds(exp)=0;
3844: subs(exp)=0;
3845: offs(exp)= (ok==10) ? 1 : 0;
3846: as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
3847: }
3848: break;
3849: default:
3850: abort();
3851: }
3852: if(input_line_pointer!=exp->e_end+1)
3853: as_bad("Ignoring junk after expression");
3854: exp->e_end[1]=c_save;
3855: input_line_pointer=save_in;
3856: if(exp->e_siz) {
3857: switch(exp->e_siz) {
3858: case 1:
3859: if(!isbyte(offs(exp)))
3860: as_warn("expression doesn't fit in BYTE");
3861: break;
3862: case 2:
3863: if(!isword(offs(exp)))
3864: as_warn("expression doesn't fit in WORD");
3865: break;
3866: }
3867: }
3868: return offs(exp);
3869:
3870: #endif /* !defined(TEST2) */
3871: }
3872:
3873: /* These are the back-ends for the various machine dependent pseudo-ops. */
3874: void demand_empty_rest_of_line(); /* Hate those extra verbose names */
3875:
3876: static
3877: void
3878: s_even(
3879: int value)
3880: {
3881: register int temp;
3882: register long int temp_fill;
3883:
3884: temp = 1; /* JF should be 2? */
3885: temp_fill = get_absolute_expression ();
3886: frag_align(temp, (int)temp_fill);
3887: /*
3888: * If this alignment is larger than any previous alignment then this
3889: * becomes the section's alignment.
3890: */
3891: if(frchain_now->frch_section.align < temp)
3892: frchain_now->frch_section.align = temp;
3893: demand_empty_rest_of_line();
3894: }
3895:
3896: static
3897: void
3898: s_proc(
3899: int value)
3900: {
3901: demand_empty_rest_of_line();
3902: }
3903:
3904: /* s_space is defined in read.c .skip is simply an alias to it. */
3905:
3906: int
3907: md_parse_option(
3908: char **argP,
3909: int *cntP,
3910: char ***vecP)
3911: {
3912: switch(**argP) {
3913: case 'l': /* -l means keep external to 32 bit offset
3914: rather than 16 bit one */
3915: break;
3916:
3917: case 'm':
3918: /* Gas simply ignores this option! */
3919: (*argP)++;
3920: if(**argP=='c')
3921: (*argP)++;
3922: if(!strcmp(*argP,"68000"))
3923: flagseen['m']=2;
3924: else if(!strcmp(*argP,"68010")) {
3925: flagseen['m']=1;
3926: } else if(!strcmp(*argP,"68020"))
3927: flagseen['m']=0;
3928: else
3929: as_warn("Unknown -m option ignored");
3930: while(**argP)
3931: (*argP)++;
3932: break;
3933:
3934: default:
3935: return 0;
3936: }
3937: return 1;
3938: }
3939:
3940:
3941: #ifdef TEST2
3942:
3943: /* TEST2: Test md_assemble() */
3944:
3945: static
3946: int
3947: is_label(
3948: char *str)
3949: {
3950: while(*str == ' ')
3951: str++;
3952: while(*str && *str != ' ')
3953: str++;
3954: if(str[-1] == ':' || str[1] == '=')
3955: return(1);
3956: return(0);
3957: }
3958:
3959: void
3960: main(
3961: int argc,
3962: char *argv[],
3963: char *envp[])
3964: {
3965: char buf[120];
3966: char *cp;
3967: int n;
3968:
3969: m68_ip_begin();
3970: for(;;){
3971: if(!gets(buf) || !*buf)
3972: break;
3973: if(buf[0] == '|' || buf[1] == '.')
3974: continue;
3975: for(cp = buf; *cp; cp++)
3976: if(*cp == '\t')
3977: *cp = ' ';
3978: if(is_label(buf))
3979: continue;
3980: memset(&the_ins, '\0', sizeof(the_ins));
3981: m68_ip(buf);
3982: if(the_ins.error){
3983: printf("Error %s in %s\n", the_ins.error, buf);
3984: }
3985: else{
3986: printf("Opcode(%d.%s): ", the_ins.numo, the_ins.args);
3987: for(n = 0; n < the_ins.numo; n++)
3988: printf(" 0x%x", the_ins.opcode[n] & 0xffff);
3989: printf(" ");
3990: print_the_insn(&the_ins.opcode[0], stdout);
3991: (void)putchar('\n');
3992: }
3993: for(n = 0; n < strlen(the_ins.args) / 2; n++){
3994: if(the_ins.operands[n].error){
3995: printf("op%d Error %s in %s\n",
3996: n, the_ins.operands[n].error, buf);
3997: continue;
3998: }
3999: printf("mode %d, reg %d, ",
4000: the_ins.operands[n].mode, the_ins.operands[n].reg);
4001: if(the_ins.operands[n].con1)
4002: printf("con1: '%.*s', ",
4003: 1 + the_ins.operands[n].con1->e_end -
4004: the_ins.operands[n].con1->e_beg,
4005: the_ins.operands[n].con1->e_beg);
4006: printf("ireg %d, isiz %d, imul %d, ",
4007: the_ins.operands[n].ireg,
4008: the_ins.operands[n].isiz,
4009: the_ins.operands[n].imul);
4010: if(the_ins.operands[n].con2)
4011: printf("con2: '%.*s',",
4012: 1 + the_ins.operands[n].con2->e_end -
4013: the_ins.operands[n].con2->e_beg,
4014: the_ins.operands[n].con2->e_beg);
4015: (void)putchar('\n');
4016: }
4017: }
4018: m68_ip_end();
4019: }
4020: #endif /* TEST2 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.