1440a403fSchristos /* tc-pdp11.c - pdp11-specific -
2*b88e3e88Schristos Copyright (C) 2001-2020 Free Software Foundation, Inc.
3440a403fSchristos
4440a403fSchristos This file is part of GAS, the GNU Assembler.
5440a403fSchristos
6440a403fSchristos GAS is free software; you can redistribute it and/or modify
7440a403fSchristos it under the terms of the GNU General Public License as published by
8440a403fSchristos the Free Software Foundation; either version 3, or (at your option)
9440a403fSchristos any later version.
10440a403fSchristos
11440a403fSchristos GAS is distributed in the hope that it will be useful,
12440a403fSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
13440a403fSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14440a403fSchristos GNU General Public License for more details.
15440a403fSchristos
16440a403fSchristos You should have received a copy of the GNU General Public License
17440a403fSchristos along with GAS; see the file COPYING. If not, write to
18440a403fSchristos the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19440a403fSchristos Boston, MA 02110-1301, USA. */
20440a403fSchristos
21440a403fSchristos #include "as.h"
22440a403fSchristos #include "safe-ctype.h"
23440a403fSchristos #include "opcode/pdp11.h"
24440a403fSchristos
25440a403fSchristos extern int flonum_gen2vax (int, FLONUM_TYPE * f, LITTLENUM_TYPE *);
26440a403fSchristos
27440a403fSchristos #define TRUE 1
28440a403fSchristos #define FALSE 0
29440a403fSchristos
30440a403fSchristos /* A representation for PDP-11 machine code. */
31440a403fSchristos struct pdp11_code
32440a403fSchristos {
33440a403fSchristos const char *error;
34440a403fSchristos int code;
35440a403fSchristos int additional; /* Is there an additional word? */
36440a403fSchristos int word; /* Additional word, if any. */
37440a403fSchristos struct
38440a403fSchristos {
39440a403fSchristos bfd_reloc_code_real_type type;
40440a403fSchristos expressionS exp;
41440a403fSchristos int pc_rel;
42440a403fSchristos } reloc;
43440a403fSchristos };
44440a403fSchristos
45440a403fSchristos /* Instruction set extensions.
46440a403fSchristos
47440a403fSchristos If you change this from an array to something else, please update
48440a403fSchristos the "PDP-11 instruction set extensions" comment in pdp11.h. */
49440a403fSchristos int pdp11_extension[PDP11_EXT_NUM];
50440a403fSchristos
51440a403fSchristos /* Assembly options. */
52440a403fSchristos
53440a403fSchristos #define ASM_OPT_PIC 1
54440a403fSchristos #define ASM_OPT_NUM 2
55440a403fSchristos
56440a403fSchristos int asm_option[ASM_OPT_NUM];
57440a403fSchristos
58440a403fSchristos /* These chars start a comment anywhere in a source file (except inside
59440a403fSchristos another comment. */
60440a403fSchristos const char comment_chars[] = "#/";
61440a403fSchristos
62440a403fSchristos /* These chars only start a comment at the beginning of a line. */
63440a403fSchristos const char line_comment_chars[] = "#/";
64440a403fSchristos
65440a403fSchristos const char line_separator_chars[] = ";";
66440a403fSchristos
67440a403fSchristos /* Chars that can be used to separate mant from exp in floating point nums. */
68440a403fSchristos const char EXP_CHARS[] = "eE";
69440a403fSchristos
70440a403fSchristos /* Chars that mean this number is a floating point constant. */
71440a403fSchristos /* as in 0f123.456. */
72440a403fSchristos /* or 0H1.234E-12 (see exp chars above). */
73440a403fSchristos const char FLT_CHARS[] = "dDfF";
74440a403fSchristos
75440a403fSchristos void pseudo_even (int);
76440a403fSchristos void pseudo_bss (int);
77440a403fSchristos
78440a403fSchristos const pseudo_typeS md_pseudo_table[] =
79440a403fSchristos {
80440a403fSchristos { "bss", pseudo_bss, 0 },
81440a403fSchristos { "even", pseudo_even, 0 },
82440a403fSchristos { 0, 0, 0 },
83440a403fSchristos };
84440a403fSchristos
85440a403fSchristos static struct hash_control *insn_hash = NULL;
86440a403fSchristos
87440a403fSchristos static int
set_option(const char * arg)88440a403fSchristos set_option (const char *arg)
89440a403fSchristos {
90440a403fSchristos int yes = 1;
91440a403fSchristos
92440a403fSchristos if (strcmp (arg, "all-extensions") == 0
93440a403fSchristos || strcmp (arg, "all") == 0)
94440a403fSchristos {
95440a403fSchristos memset (pdp11_extension, ~0, sizeof pdp11_extension);
96440a403fSchristos pdp11_extension[PDP11_NONE] = 0;
97440a403fSchristos return 1;
98440a403fSchristos }
99440a403fSchristos else if (strcmp (arg, "no-extensions") == 0)
100440a403fSchristos {
101440a403fSchristos memset (pdp11_extension, 0, sizeof pdp11_extension);
102440a403fSchristos pdp11_extension[PDP11_BASIC] = 1;
103440a403fSchristos return 1;
104440a403fSchristos }
105440a403fSchristos
106440a403fSchristos if (strncmp (arg, "no-", 3) == 0)
107440a403fSchristos {
108440a403fSchristos yes = 0;
109440a403fSchristos arg += 3;
110440a403fSchristos }
111440a403fSchristos
11206324dcfSchristos /* Commercial instructions. */
113440a403fSchristos if (strcmp (arg, "cis") == 0)
114440a403fSchristos pdp11_extension[PDP11_CIS] = yes;
115440a403fSchristos /* Call supervisor mode. */
116440a403fSchristos else if (strcmp (arg, "csm") == 0)
117440a403fSchristos pdp11_extension[PDP11_CSM] = yes;
118440a403fSchristos /* Extended instruction set. */
119440a403fSchristos else if (strcmp (arg, "eis") == 0)
120440a403fSchristos pdp11_extension[PDP11_EIS] = pdp11_extension[PDP11_LEIS] = yes;
121440a403fSchristos /* KEV11 floating-point. */
122440a403fSchristos else if (strcmp (arg, "fis") == 0
123440a403fSchristos || strcmp (arg, "kev11") == 0
124440a403fSchristos || strcmp (arg, "kev-11") == 0)
125440a403fSchristos pdp11_extension[PDP11_FIS] = yes;
126440a403fSchristos /* FP-11 floating-point. */
127440a403fSchristos else if (strcmp (arg, "fpp") == 0
128440a403fSchristos || strcmp (arg, "fpu") == 0
129440a403fSchristos || strcmp (arg, "fp11") == 0
130440a403fSchristos || strcmp (arg, "fp-11") == 0
131440a403fSchristos || strcmp (arg, "fpj11") == 0
132440a403fSchristos || strcmp (arg, "fp-j11") == 0
133440a403fSchristos || strcmp (arg, "fpj-11") == 0)
134440a403fSchristos pdp11_extension[PDP11_FPP] = yes;
135440a403fSchristos /* Limited extended insns. */
136440a403fSchristos else if (strcmp (arg, "limited-eis") == 0)
137440a403fSchristos {
138440a403fSchristos pdp11_extension[PDP11_LEIS] = yes;
139440a403fSchristos if (!pdp11_extension[PDP11_LEIS])
140440a403fSchristos pdp11_extension[PDP11_EIS] = 0;
141440a403fSchristos }
142440a403fSchristos /* Move from processor type. */
143440a403fSchristos else if (strcmp (arg, "mfpt") == 0)
144440a403fSchristos pdp11_extension[PDP11_MFPT] = yes;
145440a403fSchristos /* Multiprocessor insns: */
146440a403fSchristos else if (strncmp (arg, "mproc", 5) == 0
147440a403fSchristos /* TSTSET, WRTLCK */
148440a403fSchristos || strncmp (arg, "multiproc", 9) == 0)
149440a403fSchristos pdp11_extension[PDP11_MPROC] = yes;
150440a403fSchristos /* Move from/to proc status. */
151440a403fSchristos else if (strcmp (arg, "mxps") == 0)
152440a403fSchristos pdp11_extension[PDP11_MXPS] = yes;
153440a403fSchristos /* Position-independent code. */
154440a403fSchristos else if (strcmp (arg, "pic") == 0)
155440a403fSchristos asm_option[ASM_OPT_PIC] = yes;
156440a403fSchristos /* Set priority level. */
157440a403fSchristos else if (strcmp (arg, "spl") == 0)
158440a403fSchristos pdp11_extension[PDP11_SPL] = yes;
159440a403fSchristos /* Microcode instructions: */
160440a403fSchristos else if (strcmp (arg, "ucode") == 0
161440a403fSchristos /* LDUB, MED, XFC */
162440a403fSchristos || strcmp (arg, "microcode") == 0)
163440a403fSchristos pdp11_extension[PDP11_UCODE] = yes;
164440a403fSchristos else
165440a403fSchristos return 0;
166440a403fSchristos
167440a403fSchristos return 1;
168440a403fSchristos }
169440a403fSchristos
170440a403fSchristos
171440a403fSchristos static void
init_defaults(void)172440a403fSchristos init_defaults (void)
173440a403fSchristos {
174440a403fSchristos static int first = 1;
175440a403fSchristos
176440a403fSchristos if (first)
177440a403fSchristos {
178440a403fSchristos set_option ("all-extensions");
179440a403fSchristos set_option ("pic");
180440a403fSchristos first = 0;
181440a403fSchristos }
182440a403fSchristos }
183440a403fSchristos
184440a403fSchristos void
md_begin(void)185440a403fSchristos md_begin (void)
186440a403fSchristos {
187440a403fSchristos int i;
188440a403fSchristos
189440a403fSchristos init_defaults ();
190440a403fSchristos
191440a403fSchristos insn_hash = hash_new ();
192440a403fSchristos if (insn_hash == NULL)
193440a403fSchristos as_fatal (_("Virtual memory exhausted"));
194440a403fSchristos
195440a403fSchristos for (i = 0; i < pdp11_num_opcodes; i++)
196440a403fSchristos hash_insert (insn_hash, pdp11_opcodes[i].name, (void *) (pdp11_opcodes + i));
197440a403fSchristos for (i = 0; i < pdp11_num_aliases; i++)
198440a403fSchristos hash_insert (insn_hash, pdp11_aliases[i].name, (void *) (pdp11_aliases + i));
199440a403fSchristos }
200440a403fSchristos
201440a403fSchristos void
md_number_to_chars(char con[],valueT value,int nbytes)202440a403fSchristos md_number_to_chars (char con[], valueT value, int nbytes)
203440a403fSchristos {
204440a403fSchristos /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
205440a403fSchristos 0x12345678 is stored as "\x56\x78\x12\x34". It's
20606324dcfSchristos anyone's guess what 0x123456 would be stored like. */
207440a403fSchristos
208440a403fSchristos switch (nbytes)
209440a403fSchristos {
210440a403fSchristos case 0:
211440a403fSchristos break;
212440a403fSchristos case 1:
213440a403fSchristos con[0] = value & 0xff;
214440a403fSchristos break;
215440a403fSchristos case 2:
216440a403fSchristos con[0] = value & 0xff;
217440a403fSchristos con[1] = (value >> 8) & 0xff;
218440a403fSchristos break;
219440a403fSchristos case 4:
220440a403fSchristos con[0] = (value >> 16) & 0xff;
221440a403fSchristos con[1] = (value >> 24) & 0xff;
222440a403fSchristos con[2] = value & 0xff;
223440a403fSchristos con[3] = (value >> 8) & 0xff;
224440a403fSchristos break;
225440a403fSchristos default:
226440a403fSchristos BAD_CASE (nbytes);
227440a403fSchristos }
228440a403fSchristos }
229440a403fSchristos
230440a403fSchristos /* Fix up some data or instructions after we find out the value of a symbol
231440a403fSchristos that they reference. Knows about order of bytes in address. */
232440a403fSchristos
233440a403fSchristos void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)234440a403fSchristos md_apply_fix (fixS *fixP,
235440a403fSchristos valueT * valP,
236440a403fSchristos segT seg ATTRIBUTE_UNUSED)
237440a403fSchristos {
238440a403fSchristos valueT code;
239440a403fSchristos valueT mask;
240440a403fSchristos valueT val = * valP;
241440a403fSchristos char *buf;
242440a403fSchristos int shift;
243440a403fSchristos int size;
244440a403fSchristos
245440a403fSchristos buf = fixP->fx_where + fixP->fx_frag->fr_literal;
246440a403fSchristos size = fixP->fx_size;
247440a403fSchristos code = md_chars_to_number ((unsigned char *) buf, size);
248440a403fSchristos
249440a403fSchristos switch (fixP->fx_r_type)
250440a403fSchristos {
251*b88e3e88Schristos case BFD_RELOC_8:
252*b88e3e88Schristos mask = 0xff;
253*b88e3e88Schristos shift = 0;
254*b88e3e88Schristos break;
255440a403fSchristos case BFD_RELOC_16:
256440a403fSchristos case BFD_RELOC_16_PCREL:
257440a403fSchristos mask = 0xffff;
258440a403fSchristos shift = 0;
259440a403fSchristos break;
260440a403fSchristos case BFD_RELOC_PDP11_DISP_8_PCREL:
261440a403fSchristos mask = 0x00ff;
262440a403fSchristos shift = 1;
263440a403fSchristos break;
264440a403fSchristos case BFD_RELOC_PDP11_DISP_6_PCREL:
265440a403fSchristos mask = 0x003f;
266440a403fSchristos shift = 1;
267440a403fSchristos val = -val;
268440a403fSchristos break;
269440a403fSchristos default:
270440a403fSchristos BAD_CASE (fixP->fx_r_type);
271440a403fSchristos }
272440a403fSchristos
273440a403fSchristos if (fixP->fx_addsy != NULL)
274440a403fSchristos val += symbol_get_bfdsym (fixP->fx_addsy)->section->vma;
275440a403fSchristos /* *value += fixP->fx_addsy->bsym->section->vma; */
276440a403fSchristos
277440a403fSchristos code &= ~mask;
278440a403fSchristos code |= (val >> shift) & mask;
279440a403fSchristos number_to_chars_littleendian (buf, code, size);
280440a403fSchristos
281440a403fSchristos if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
282440a403fSchristos fixP->fx_done = 1;
283440a403fSchristos }
284440a403fSchristos
285440a403fSchristos long
md_chars_to_number(unsigned char * con,int nbytes)286440a403fSchristos md_chars_to_number (unsigned char *con, int nbytes)
287440a403fSchristos {
288440a403fSchristos /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
289440a403fSchristos 0x12345678 is stored as "\x56\x78\x12\x34". It's
29006324dcfSchristos anyone's guess what 0x123456 would be stored like. */
291440a403fSchristos switch (nbytes)
292440a403fSchristos {
293440a403fSchristos case 0:
294440a403fSchristos return 0;
295440a403fSchristos case 1:
296440a403fSchristos return con[0];
297440a403fSchristos case 2:
298440a403fSchristos return (con[1] << BITS_PER_CHAR) | con[0];
299440a403fSchristos case 4:
300440a403fSchristos return
301440a403fSchristos (((con[1] << BITS_PER_CHAR) | con[0]) << (2 * BITS_PER_CHAR))
302440a403fSchristos |((con[3] << BITS_PER_CHAR) | con[2]);
303440a403fSchristos default:
304440a403fSchristos BAD_CASE (nbytes);
305440a403fSchristos return 0;
306440a403fSchristos }
307440a403fSchristos }
308440a403fSchristos
309440a403fSchristos static char *
skip_whitespace(char * str)310440a403fSchristos skip_whitespace (char *str)
311440a403fSchristos {
312440a403fSchristos while (*str == ' ' || *str == '\t')
313440a403fSchristos str++;
314440a403fSchristos return str;
315440a403fSchristos }
316440a403fSchristos
317440a403fSchristos static char *
find_whitespace(char * str)318440a403fSchristos find_whitespace (char *str)
319440a403fSchristos {
320440a403fSchristos while (*str != ' ' && *str != '\t' && *str != 0)
321440a403fSchristos str++;
322440a403fSchristos return str;
323440a403fSchristos }
324440a403fSchristos
325440a403fSchristos static char *
parse_reg(char * str,struct pdp11_code * operand)326440a403fSchristos parse_reg (char *str, struct pdp11_code *operand)
327440a403fSchristos {
328440a403fSchristos str = skip_whitespace (str);
329440a403fSchristos if (TOLOWER (*str) == 'r')
330440a403fSchristos {
331440a403fSchristos str++;
332440a403fSchristos switch (*str)
333440a403fSchristos {
334440a403fSchristos case '0': case '1': case '2': case '3':
335440a403fSchristos case '4': case '5': case '6': case '7':
336440a403fSchristos operand->code = *str - '0';
337440a403fSchristos str++;
338440a403fSchristos break;
339440a403fSchristos default:
340440a403fSchristos operand->error = _("Bad register name");
341440a403fSchristos return str - 1;
342440a403fSchristos }
343440a403fSchristos }
344440a403fSchristos else if (strncmp (str, "sp", 2) == 0
345440a403fSchristos || strncmp (str, "SP", 2) == 0)
346440a403fSchristos {
347440a403fSchristos operand->code = 6;
348440a403fSchristos str += 2;
349440a403fSchristos }
350440a403fSchristos else if (strncmp (str, "pc", 2) == 0
351440a403fSchristos || strncmp (str, "PC", 2) == 0)
352440a403fSchristos {
353440a403fSchristos operand->code = 7;
354440a403fSchristos str += 2;
355440a403fSchristos }
356440a403fSchristos else
357440a403fSchristos operand->error = _("Bad register name");
358440a403fSchristos
359440a403fSchristos return str;
360440a403fSchristos }
361440a403fSchristos
362440a403fSchristos static char *
parse_ac5(char * str,struct pdp11_code * operand)363440a403fSchristos parse_ac5 (char *str, struct pdp11_code *operand)
364440a403fSchristos {
365440a403fSchristos str = skip_whitespace (str);
366440a403fSchristos if (strncmp (str, "fr", 2) == 0
367440a403fSchristos || strncmp (str, "FR", 2) == 0
368440a403fSchristos || strncmp (str, "ac", 2) == 0
369440a403fSchristos || strncmp (str, "AC", 2) == 0)
370440a403fSchristos {
371440a403fSchristos str += 2;
372440a403fSchristos switch (*str)
373440a403fSchristos {
374440a403fSchristos case '0': case '1': case '2': case '3':
375440a403fSchristos case '4': case '5':
376440a403fSchristos operand->code = *str - '0';
377440a403fSchristos str++;
378440a403fSchristos break;
379440a403fSchristos default:
380440a403fSchristos operand->error = _("Bad register name");
381440a403fSchristos return str - 2;
382440a403fSchristos }
383440a403fSchristos }
384440a403fSchristos else
385440a403fSchristos {
386440a403fSchristos operand->error = _("Bad register name");
387440a403fSchristos return str;
388440a403fSchristos }
389440a403fSchristos
390440a403fSchristos return str;
391440a403fSchristos }
392440a403fSchristos
393440a403fSchristos static char *
parse_ac(char * str,struct pdp11_code * operand)394440a403fSchristos parse_ac (char *str, struct pdp11_code *operand)
395440a403fSchristos {
396440a403fSchristos str = parse_ac5 (str, operand);
397440a403fSchristos if (!operand->error && operand->code > 3)
398440a403fSchristos {
399440a403fSchristos operand->error = _("Bad register name");
400440a403fSchristos return str - 3;
401440a403fSchristos }
402440a403fSchristos
403440a403fSchristos return str;
404440a403fSchristos }
405440a403fSchristos
406440a403fSchristos static char *
parse_expression(char * str,struct pdp11_code * operand)407440a403fSchristos parse_expression (char *str, struct pdp11_code *operand)
408440a403fSchristos {
409440a403fSchristos char *save_input_line_pointer;
410440a403fSchristos segT seg;
411440a403fSchristos
412440a403fSchristos save_input_line_pointer = input_line_pointer;
413440a403fSchristos input_line_pointer = str;
414440a403fSchristos seg = expression (&operand->reloc.exp);
415440a403fSchristos if (seg == NULL)
416440a403fSchristos {
417440a403fSchristos input_line_pointer = save_input_line_pointer;
418440a403fSchristos operand->error = _("Error in expression");
419440a403fSchristos return str;
420440a403fSchristos }
421440a403fSchristos
422440a403fSchristos str = input_line_pointer;
423440a403fSchristos input_line_pointer = save_input_line_pointer;
424440a403fSchristos
425440a403fSchristos operand->reloc.pc_rel = 0;
426440a403fSchristos
427440a403fSchristos return str;
428440a403fSchristos }
429440a403fSchristos
430440a403fSchristos static char *
parse_op_no_deferred(char * str,struct pdp11_code * operand)431440a403fSchristos parse_op_no_deferred (char *str, struct pdp11_code *operand)
432440a403fSchristos {
433440a403fSchristos LITTLENUM_TYPE literal_float[2];
434440a403fSchristos
435440a403fSchristos str = skip_whitespace (str);
436440a403fSchristos
437440a403fSchristos switch (*str)
438440a403fSchristos {
439440a403fSchristos case '(': /* (rn) and (rn)+ */
440440a403fSchristos str = parse_reg (str + 1, operand);
441440a403fSchristos if (operand->error)
442440a403fSchristos return str;
443440a403fSchristos str = skip_whitespace (str);
444440a403fSchristos if (*str != ')')
445440a403fSchristos {
446440a403fSchristos operand->error = _("Missing ')'");
447440a403fSchristos return str;
448440a403fSchristos }
449440a403fSchristos str++;
450440a403fSchristos if (*str == '+')
451440a403fSchristos {
452440a403fSchristos operand->code |= 020;
453440a403fSchristos str++;
454440a403fSchristos }
455440a403fSchristos else
456440a403fSchristos {
457440a403fSchristos operand->code |= 010;
458440a403fSchristos }
459440a403fSchristos break;
460440a403fSchristos
461440a403fSchristos /* Immediate. */
462440a403fSchristos case '#':
463440a403fSchristos case '$':
464440a403fSchristos str = parse_expression (str + 1, operand);
465440a403fSchristos if (operand->error)
466440a403fSchristos return str;
467440a403fSchristos operand->additional = TRUE;
468440a403fSchristos operand->word = operand->reloc.exp.X_add_number;
469440a403fSchristos switch (operand->reloc.exp.X_op)
470440a403fSchristos {
471440a403fSchristos case O_constant:
472440a403fSchristos break;
473440a403fSchristos case O_symbol:
474440a403fSchristos case O_add:
475440a403fSchristos case O_subtract:
476440a403fSchristos operand->reloc.type = BFD_RELOC_16;
477440a403fSchristos operand->reloc.pc_rel = 0;
478440a403fSchristos break;
479440a403fSchristos case O_big:
480440a403fSchristos if (operand->reloc.exp.X_add_number > 0)
481440a403fSchristos {
482440a403fSchristos operand->error = _("Error in expression");
483440a403fSchristos break;
484440a403fSchristos }
485440a403fSchristos /* It's a floating literal... */
486440a403fSchristos know (operand->reloc.exp.X_add_number < 0);
487440a403fSchristos flonum_gen2vax ('f', &generic_floating_point_number, literal_float);
488440a403fSchristos operand->word = literal_float[0];
489440a403fSchristos if (literal_float[1] != 0)
490440a403fSchristos as_warn (_("Low order bits truncated in immediate float operand"));
491440a403fSchristos break;
492440a403fSchristos default:
493440a403fSchristos operand->error = _("Error in expression");
494440a403fSchristos break;
495440a403fSchristos }
496440a403fSchristos operand->code = 027;
497440a403fSchristos break;
498440a403fSchristos
499440a403fSchristos /* label, d(rn), -(rn) */
500440a403fSchristos default:
501440a403fSchristos {
502440a403fSchristos if (strncmp (str, "-(", 2) == 0) /* -(rn) */
503440a403fSchristos {
504440a403fSchristos str = parse_reg (str + 2, operand);
505440a403fSchristos if (operand->error)
506440a403fSchristos return str;
507440a403fSchristos str = skip_whitespace (str);
508440a403fSchristos if (*str != ')')
509440a403fSchristos {
510440a403fSchristos operand->error = _("Missing ')'");
511440a403fSchristos return str;
512440a403fSchristos }
513440a403fSchristos operand->code |= 040;
514440a403fSchristos str++;
515440a403fSchristos break;
516440a403fSchristos }
517440a403fSchristos
518440a403fSchristos str = parse_expression (str, operand);
519440a403fSchristos if (operand->error)
520440a403fSchristos return str;
521440a403fSchristos
522440a403fSchristos str = skip_whitespace (str);
523440a403fSchristos
524440a403fSchristos if (*str != '(')
525440a403fSchristos {
526440a403fSchristos operand->code = 067;
527440a403fSchristos operand->additional = 1;
528440a403fSchristos operand->word = 0;
529440a403fSchristos operand->reloc.type = BFD_RELOC_16_PCREL;
530440a403fSchristos operand->reloc.pc_rel = 1;
531440a403fSchristos break;
532440a403fSchristos }
533440a403fSchristos
534440a403fSchristos /* d(rn) */
535440a403fSchristos str++;
536440a403fSchristos str = parse_reg (str, operand);
537440a403fSchristos if (operand->error)
538440a403fSchristos return str;
539440a403fSchristos
540440a403fSchristos str = skip_whitespace (str);
541440a403fSchristos
542440a403fSchristos if (*str != ')')
543440a403fSchristos {
544440a403fSchristos operand->error = _("Missing ')'");
545440a403fSchristos return str;
546440a403fSchristos }
547440a403fSchristos
548440a403fSchristos str++;
549440a403fSchristos operand->additional = TRUE;
550440a403fSchristos operand->code |= 060;
551440a403fSchristos switch (operand->reloc.exp.X_op)
552440a403fSchristos {
553440a403fSchristos case O_symbol:
554440a403fSchristos operand->reloc.type = BFD_RELOC_16;
555440a403fSchristos operand->reloc.pc_rel = 0;
556440a403fSchristos break;
557440a403fSchristos case O_constant:
558440a403fSchristos if ((operand->code & 7) == 7)
559440a403fSchristos {
560440a403fSchristos operand->reloc.pc_rel = 1;
561440a403fSchristos operand->word = operand->reloc.exp.X_add_number;
562440a403fSchristos }
563440a403fSchristos else
564440a403fSchristos operand->word = operand->reloc.exp.X_add_number;
565440a403fSchristos
566440a403fSchristos break;
567440a403fSchristos default:
568440a403fSchristos BAD_CASE (operand->reloc.exp.X_op);
569440a403fSchristos }
570440a403fSchristos break;
571440a403fSchristos }
572440a403fSchristos }
573440a403fSchristos
574440a403fSchristos return str;
575440a403fSchristos }
576440a403fSchristos
577440a403fSchristos static char *
parse_op_noreg(char * str,struct pdp11_code * operand)578440a403fSchristos parse_op_noreg (char *str, struct pdp11_code *operand)
579440a403fSchristos {
580440a403fSchristos str = skip_whitespace (str);
581440a403fSchristos operand->error = NULL;
582440a403fSchristos
583440a403fSchristos if (*str == '@' || *str == '*')
584440a403fSchristos {
585*b88e3e88Schristos /* @(Rn) == @0(Rn): Mode 7, Indexed deferred.
586*b88e3e88Schristos Check for auto-increment deferred. */
587*b88e3e88Schristos if (str[1] == '('
588*b88e3e88Schristos && str[2] != 0
589*b88e3e88Schristos && str[3] != 0
590*b88e3e88Schristos && str[4] != 0
591*b88e3e88Schristos && str[5] != '+')
592*b88e3e88Schristos {
593*b88e3e88Schristos /* Change implied to explicit index deferred. */
594*b88e3e88Schristos *str = '0';
595*b88e3e88Schristos str = parse_op_no_deferred (str, operand);
596*b88e3e88Schristos }
597*b88e3e88Schristos else
598*b88e3e88Schristos {
599*b88e3e88Schristos /* @Rn == (Rn): Register deferred. */
600*b88e3e88Schristos str = parse_reg (str + 1, operand);
601*b88e3e88Schristos
602*b88e3e88Schristos /* Not @Rn */
603*b88e3e88Schristos if (operand->error)
604*b88e3e88Schristos {
605*b88e3e88Schristos operand->error = NULL;
606*b88e3e88Schristos str = parse_op_no_deferred (str, operand);
607*b88e3e88Schristos }
608*b88e3e88Schristos }
609*b88e3e88Schristos
610440a403fSchristos if (operand->error)
611440a403fSchristos return str;
612*b88e3e88Schristos
613440a403fSchristos operand->code |= 010;
614440a403fSchristos }
615440a403fSchristos else
616440a403fSchristos str = parse_op_no_deferred (str, operand);
617440a403fSchristos
618440a403fSchristos return str;
619440a403fSchristos }
620440a403fSchristos
621440a403fSchristos static char *
parse_op(char * str,struct pdp11_code * operand)622440a403fSchristos parse_op (char *str, struct pdp11_code *operand)
623440a403fSchristos {
624440a403fSchristos str = skip_whitespace (str);
625440a403fSchristos
626440a403fSchristos str = parse_reg (str, operand);
627440a403fSchristos if (!operand->error)
628440a403fSchristos return str;
629440a403fSchristos
630440a403fSchristos operand->error = NULL;
631440a403fSchristos parse_ac5 (str, operand);
632440a403fSchristos if (!operand->error)
633440a403fSchristos {
634440a403fSchristos operand->error = _("Float AC not legal as integer operand");
635440a403fSchristos return str;
636440a403fSchristos }
637440a403fSchristos
638440a403fSchristos return parse_op_noreg (str, operand);
639440a403fSchristos }
640440a403fSchristos
641440a403fSchristos static char *
parse_fop(char * str,struct pdp11_code * operand)642440a403fSchristos parse_fop (char *str, struct pdp11_code *operand)
643440a403fSchristos {
644440a403fSchristos str = skip_whitespace (str);
645440a403fSchristos
646440a403fSchristos str = parse_ac5 (str, operand);
647440a403fSchristos if (!operand->error)
648440a403fSchristos return str;
649440a403fSchristos
650440a403fSchristos operand->error = NULL;
651440a403fSchristos parse_reg (str, operand);
652440a403fSchristos if (!operand->error)
653440a403fSchristos {
654440a403fSchristos operand->error = _("General register not legal as float operand");
655440a403fSchristos return str;
656440a403fSchristos }
657440a403fSchristos
658440a403fSchristos return parse_op_noreg (str, operand);
659440a403fSchristos }
660440a403fSchristos
661440a403fSchristos static char *
parse_separator(char * str,int * error)662440a403fSchristos parse_separator (char *str, int *error)
663440a403fSchristos {
664440a403fSchristos str = skip_whitespace (str);
665440a403fSchristos *error = (*str != ',');
666440a403fSchristos if (!*error)
667440a403fSchristos str++;
668440a403fSchristos return str;
669440a403fSchristos }
670440a403fSchristos
671440a403fSchristos void
md_assemble(char * instruction_string)672440a403fSchristos md_assemble (char *instruction_string)
673440a403fSchristos {
674440a403fSchristos const struct pdp11_opcode *op;
675440a403fSchristos struct pdp11_code insn, op1, op2;
676440a403fSchristos int error;
677440a403fSchristos int size;
678440a403fSchristos const char *err = NULL;
679440a403fSchristos char *str;
680440a403fSchristos char *p;
681440a403fSchristos char c;
682440a403fSchristos
683440a403fSchristos str = skip_whitespace (instruction_string);
684440a403fSchristos p = find_whitespace (str);
685440a403fSchristos if (p - str == 0)
686440a403fSchristos {
687440a403fSchristos as_bad (_("No instruction found"));
688440a403fSchristos return;
689440a403fSchristos }
690440a403fSchristos
691440a403fSchristos c = *p;
692440a403fSchristos *p = '\0';
693440a403fSchristos op = (struct pdp11_opcode *)hash_find (insn_hash, str);
694440a403fSchristos *p = c;
695440a403fSchristos if (op == 0)
696440a403fSchristos {
697440a403fSchristos as_bad (_("Unknown instruction '%s'"), str);
698440a403fSchristos return;
699440a403fSchristos }
700440a403fSchristos
701440a403fSchristos if (!pdp11_extension[op->extension])
702440a403fSchristos {
703440a403fSchristos as_warn (_("Unsupported instruction set extension: %s"), op->name);
704440a403fSchristos return;
705440a403fSchristos }
706440a403fSchristos
707440a403fSchristos insn.error = NULL;
708440a403fSchristos insn.code = op->opcode;
709440a403fSchristos insn.reloc.type = BFD_RELOC_NONE;
710440a403fSchristos op1.error = NULL;
711440a403fSchristos op1.additional = FALSE;
712440a403fSchristos op1.reloc.type = BFD_RELOC_NONE;
713440a403fSchristos op2.error = NULL;
714440a403fSchristos op2.additional = FALSE;
715440a403fSchristos op2.reloc.type = BFD_RELOC_NONE;
716440a403fSchristos
717440a403fSchristos str = p;
718440a403fSchristos size = 2;
719440a403fSchristos
720440a403fSchristos switch (op->type)
721440a403fSchristos {
722440a403fSchristos case PDP11_OPCODE_NO_OPS:
723440a403fSchristos str = skip_whitespace (str);
724440a403fSchristos break;
725440a403fSchristos
726440a403fSchristos case PDP11_OPCODE_IMM3:
727440a403fSchristos case PDP11_OPCODE_IMM6:
728440a403fSchristos case PDP11_OPCODE_IMM8:
729440a403fSchristos str = skip_whitespace (str);
730440a403fSchristos if (*str == '#' || *str == '$')
731440a403fSchristos str++;
732440a403fSchristos str = parse_expression (str, &op1);
733440a403fSchristos if (op1.error)
734440a403fSchristos break;
735440a403fSchristos if (op1.reloc.exp.X_op != O_constant || op1.reloc.type != BFD_RELOC_NONE)
736440a403fSchristos {
737440a403fSchristos op1.error = _("operand is not an absolute constant");
738440a403fSchristos break;
739440a403fSchristos }
740440a403fSchristos switch (op->type)
741440a403fSchristos {
742440a403fSchristos case PDP11_OPCODE_IMM3:
743440a403fSchristos if (op1.reloc.exp.X_add_number & ~7)
744440a403fSchristos {
745440a403fSchristos op1.error = _("3-bit immediate out of range");
746440a403fSchristos break;
747440a403fSchristos }
748440a403fSchristos break;
749440a403fSchristos case PDP11_OPCODE_IMM6:
750440a403fSchristos if (op1.reloc.exp.X_add_number & ~0x3f)
751440a403fSchristos {
752440a403fSchristos op1.error = _("6-bit immediate out of range");
753440a403fSchristos break;
754440a403fSchristos }
755440a403fSchristos break;
756440a403fSchristos case PDP11_OPCODE_IMM8:
757440a403fSchristos if (op1.reloc.exp.X_add_number & ~0xff)
758440a403fSchristos {
759440a403fSchristos op1.error = _("8-bit immediate out of range");
760440a403fSchristos break;
761440a403fSchristos }
762440a403fSchristos break;
763440a403fSchristos }
764440a403fSchristos insn.code |= op1.reloc.exp.X_add_number;
765440a403fSchristos break;
766440a403fSchristos
767440a403fSchristos case PDP11_OPCODE_DISPL:
768440a403fSchristos {
769440a403fSchristos char *new_pointer;
770440a403fSchristos new_pointer = parse_expression (str, &op1);
771440a403fSchristos op1.code = 0;
772440a403fSchristos op1.reloc.pc_rel = 1;
773440a403fSchristos op1.reloc.type = BFD_RELOC_PDP11_DISP_8_PCREL;
774440a403fSchristos if (op1.reloc.exp.X_op != O_symbol)
775440a403fSchristos {
776440a403fSchristos op1.error = _("Symbol expected");
777440a403fSchristos break;
778440a403fSchristos }
779440a403fSchristos if (op1.code & ~0xff)
780440a403fSchristos {
781440a403fSchristos err = _("8-bit displacement out of range");
782440a403fSchristos break;
783440a403fSchristos }
784440a403fSchristos str = new_pointer;
785440a403fSchristos insn.code |= op1.code;
786440a403fSchristos insn.reloc = op1.reloc;
787440a403fSchristos }
788440a403fSchristos break;
789440a403fSchristos
790440a403fSchristos case PDP11_OPCODE_REG:
791440a403fSchristos str = parse_reg (str, &op1);
792440a403fSchristos if (op1.error)
793440a403fSchristos break;
794440a403fSchristos insn.code |= op1.code;
795440a403fSchristos break;
796440a403fSchristos
797440a403fSchristos case PDP11_OPCODE_OP:
798440a403fSchristos str = parse_op (str, &op1);
799440a403fSchristos if (op1.error)
800440a403fSchristos break;
801440a403fSchristos insn.code |= op1.code;
802440a403fSchristos if (op1.additional)
803440a403fSchristos size += 2;
804440a403fSchristos break;
805440a403fSchristos
806440a403fSchristos case PDP11_OPCODE_FOP:
807440a403fSchristos str = parse_fop (str, &op1);
808440a403fSchristos if (op1.error)
809440a403fSchristos break;
810440a403fSchristos insn.code |= op1.code;
811440a403fSchristos if (op1.additional)
812440a403fSchristos size += 2;
813440a403fSchristos break;
814440a403fSchristos
815440a403fSchristos case PDP11_OPCODE_REG_OP:
816440a403fSchristos str = parse_reg (str, &op2);
817440a403fSchristos if (op2.error)
818440a403fSchristos break;
819440a403fSchristos insn.code |= op2.code << 6;
820440a403fSchristos str = parse_separator (str, &error);
821440a403fSchristos if (error)
822440a403fSchristos {
823440a403fSchristos op2.error = _("Missing ','");
824440a403fSchristos break;
825440a403fSchristos }
826440a403fSchristos str = parse_op (str, &op1);
827440a403fSchristos if (op1.error)
828440a403fSchristos break;
829440a403fSchristos insn.code |= op1.code;
830440a403fSchristos if (op1.additional)
831440a403fSchristos size += 2;
832440a403fSchristos break;
833440a403fSchristos
834440a403fSchristos case PDP11_OPCODE_REG_OP_REV:
835440a403fSchristos str = parse_op (str, &op1);
836440a403fSchristos if (op1.error)
837440a403fSchristos break;
838440a403fSchristos insn.code |= op1.code;
839440a403fSchristos if (op1.additional)
840440a403fSchristos size += 2;
841440a403fSchristos str = parse_separator (str, &error);
842440a403fSchristos if (error)
843440a403fSchristos {
844440a403fSchristos op2.error = _("Missing ','");
845440a403fSchristos break;
846440a403fSchristos }
847440a403fSchristos str = parse_reg (str, &op2);
848440a403fSchristos if (op2.error)
849440a403fSchristos break;
850440a403fSchristos insn.code |= op2.code << 6;
851440a403fSchristos break;
852440a403fSchristos
853440a403fSchristos case PDP11_OPCODE_AC_FOP:
854440a403fSchristos str = parse_ac (str, &op2);
855440a403fSchristos if (op2.error)
856440a403fSchristos break;
857440a403fSchristos insn.code |= op2.code << 6;
858440a403fSchristos str = parse_separator (str, &error);
859440a403fSchristos if (error)
860440a403fSchristos {
861440a403fSchristos op1.error = _("Missing ','");
862440a403fSchristos break;
863440a403fSchristos }
864440a403fSchristos str = parse_fop (str, &op1);
865440a403fSchristos if (op1.error)
866440a403fSchristos break;
867440a403fSchristos insn.code |= op1.code;
868440a403fSchristos if (op1.additional)
869440a403fSchristos size += 2;
870440a403fSchristos break;
871440a403fSchristos
872440a403fSchristos case PDP11_OPCODE_FOP_AC:
873440a403fSchristos str = parse_fop (str, &op1);
874440a403fSchristos if (op1.error)
875440a403fSchristos break;
876440a403fSchristos insn.code |= op1.code;
877440a403fSchristos if (op1.additional)
878440a403fSchristos size += 2;
879440a403fSchristos str = parse_separator (str, &error);
880440a403fSchristos if (error)
881440a403fSchristos {
882440a403fSchristos op1.error = _("Missing ','");
883440a403fSchristos break;
884440a403fSchristos }
885440a403fSchristos str = parse_ac (str, &op2);
886440a403fSchristos if (op2.error)
887440a403fSchristos break;
888440a403fSchristos insn.code |= op2.code << 6;
889440a403fSchristos break;
890440a403fSchristos
891440a403fSchristos case PDP11_OPCODE_AC_OP:
892440a403fSchristos str = parse_ac (str, &op2);
893440a403fSchristos if (op2.error)
894440a403fSchristos break;
895440a403fSchristos insn.code |= op2.code << 6;
896440a403fSchristos str = parse_separator (str, &error);
897440a403fSchristos if (error)
898440a403fSchristos {
899440a403fSchristos op1.error = _("Missing ','");
900440a403fSchristos break;
901440a403fSchristos }
902440a403fSchristos str = parse_op (str, &op1);
903440a403fSchristos if (op1.error)
904440a403fSchristos break;
905440a403fSchristos insn.code |= op1.code;
906440a403fSchristos if (op1.additional)
907440a403fSchristos size += 2;
908440a403fSchristos break;
909440a403fSchristos
910440a403fSchristos case PDP11_OPCODE_OP_AC:
911440a403fSchristos str = parse_op (str, &op1);
912440a403fSchristos if (op1.error)
913440a403fSchristos break;
914440a403fSchristos insn.code |= op1.code;
915440a403fSchristos if (op1.additional)
916440a403fSchristos size += 2;
917440a403fSchristos str = parse_separator (str, &error);
918440a403fSchristos if (error)
919440a403fSchristos {
920440a403fSchristos op1.error = _("Missing ','");
921440a403fSchristos break;
922440a403fSchristos }
923440a403fSchristos str = parse_ac (str, &op2);
924440a403fSchristos if (op2.error)
925440a403fSchristos break;
926440a403fSchristos insn.code |= op2.code << 6;
927440a403fSchristos break;
928440a403fSchristos
929440a403fSchristos case PDP11_OPCODE_OP_OP:
930440a403fSchristos str = parse_op (str, &op1);
931440a403fSchristos if (op1.error)
932440a403fSchristos break;
933440a403fSchristos insn.code |= op1.code << 6;
934440a403fSchristos if (op1.additional)
935440a403fSchristos size += 2;
936440a403fSchristos str = parse_separator (str, &error);
937440a403fSchristos if (error)
938440a403fSchristos {
939440a403fSchristos op2.error = _("Missing ','");
940440a403fSchristos break;
941440a403fSchristos }
942440a403fSchristos str = parse_op (str, &op2);
943440a403fSchristos if (op2.error)
944440a403fSchristos break;
945440a403fSchristos insn.code |= op2.code;
946440a403fSchristos if (op2.additional)
947440a403fSchristos size += 2;
948440a403fSchristos break;
949440a403fSchristos
950440a403fSchristos case PDP11_OPCODE_REG_DISPL:
951440a403fSchristos {
952440a403fSchristos char *new_pointer;
953440a403fSchristos str = parse_reg (str, &op2);
954440a403fSchristos if (op2.error)
955440a403fSchristos break;
956440a403fSchristos insn.code |= op2.code << 6;
957440a403fSchristos str = parse_separator (str, &error);
958440a403fSchristos if (error)
959440a403fSchristos {
960440a403fSchristos op1.error = _("Missing ','");
961440a403fSchristos break;
962440a403fSchristos }
963440a403fSchristos new_pointer = parse_expression (str, &op1);
964440a403fSchristos op1.code = 0;
965440a403fSchristos op1.reloc.pc_rel = 1;
966440a403fSchristos op1.reloc.type = BFD_RELOC_PDP11_DISP_6_PCREL;
967440a403fSchristos if (op1.reloc.exp.X_op != O_symbol)
968440a403fSchristos {
969440a403fSchristos op1.error = _("Symbol expected");
970440a403fSchristos break;
971440a403fSchristos }
972440a403fSchristos if (op1.code & ~0x3f)
973440a403fSchristos {
974440a403fSchristos err = _("6-bit displacement out of range");
975440a403fSchristos break;
976440a403fSchristos }
977440a403fSchristos str = new_pointer;
978440a403fSchristos insn.code |= op1.code;
979440a403fSchristos insn.reloc = op1.reloc;
980440a403fSchristos }
981440a403fSchristos break;
982440a403fSchristos
983440a403fSchristos default:
984440a403fSchristos BAD_CASE (op->type);
985440a403fSchristos }
986440a403fSchristos
987440a403fSchristos if (op1.error)
988440a403fSchristos err = op1.error;
989440a403fSchristos else if (op2.error)
990440a403fSchristos err = op2.error;
991440a403fSchristos else
992440a403fSchristos {
993440a403fSchristos str = skip_whitespace (str);
994440a403fSchristos if (*str)
995440a403fSchristos err = _("Too many operands");
996440a403fSchristos }
997440a403fSchristos
998440a403fSchristos {
999440a403fSchristos char *to = NULL;
1000440a403fSchristos
1001440a403fSchristos if (err)
1002440a403fSchristos {
1003440a403fSchristos as_bad ("%s", err);
1004440a403fSchristos return;
1005440a403fSchristos }
1006440a403fSchristos
1007440a403fSchristos to = frag_more (size);
1008440a403fSchristos
1009440a403fSchristos md_number_to_chars (to, insn.code, 2);
1010440a403fSchristos if (insn.reloc.type != BFD_RELOC_NONE)
1011440a403fSchristos fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
1012440a403fSchristos &insn.reloc.exp, insn.reloc.pc_rel, insn.reloc.type);
1013440a403fSchristos to += 2;
1014440a403fSchristos
1015440a403fSchristos if (op1.additional)
1016440a403fSchristos {
1017440a403fSchristos md_number_to_chars (to, op1.word, 2);
1018440a403fSchristos if (op1.reloc.type != BFD_RELOC_NONE)
1019440a403fSchristos fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
1020440a403fSchristos &op1.reloc.exp, op1.reloc.pc_rel, op1.reloc.type);
1021440a403fSchristos to += 2;
1022440a403fSchristos }
1023440a403fSchristos
1024440a403fSchristos if (op2.additional)
1025440a403fSchristos {
1026440a403fSchristos md_number_to_chars (to, op2.word, 2);
1027440a403fSchristos if (op2.reloc.type != BFD_RELOC_NONE)
1028440a403fSchristos fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
1029440a403fSchristos &op2.reloc.exp, op2.reloc.pc_rel, op2.reloc.type);
1030440a403fSchristos }
1031440a403fSchristos }
1032440a403fSchristos }
1033440a403fSchristos
1034440a403fSchristos int
md_estimate_size_before_relax(fragS * fragP ATTRIBUTE_UNUSED,segT segment ATTRIBUTE_UNUSED)1035440a403fSchristos md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
1036440a403fSchristos segT segment ATTRIBUTE_UNUSED)
1037440a403fSchristos {
1038440a403fSchristos return 0;
1039440a403fSchristos }
1040440a403fSchristos
1041440a403fSchristos void
md_convert_frag(bfd * headers ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)1042440a403fSchristos md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
1043440a403fSchristos segT seg ATTRIBUTE_UNUSED,
1044440a403fSchristos fragS *fragP ATTRIBUTE_UNUSED)
1045440a403fSchristos {
1046440a403fSchristos }
1047440a403fSchristos
1048440a403fSchristos int md_short_jump_size = 2;
1049440a403fSchristos int md_long_jump_size = 4;
1050440a403fSchristos
1051440a403fSchristos void
md_create_short_jump(char * ptr ATTRIBUTE_UNUSED,addressT from_addr ATTRIBUTE_UNUSED,addressT to_addr ATTRIBUTE_UNUSED,fragS * frag ATTRIBUTE_UNUSED,symbolS * to_symbol ATTRIBUTE_UNUSED)1052440a403fSchristos md_create_short_jump (char *ptr ATTRIBUTE_UNUSED,
1053440a403fSchristos addressT from_addr ATTRIBUTE_UNUSED,
1054440a403fSchristos addressT to_addr ATTRIBUTE_UNUSED,
1055440a403fSchristos fragS *frag ATTRIBUTE_UNUSED,
1056440a403fSchristos symbolS *to_symbol ATTRIBUTE_UNUSED)
1057440a403fSchristos {
1058440a403fSchristos }
1059440a403fSchristos
1060440a403fSchristos void
md_create_long_jump(char * ptr ATTRIBUTE_UNUSED,addressT from_addr ATTRIBUTE_UNUSED,addressT to_addr ATTRIBUTE_UNUSED,fragS * frag ATTRIBUTE_UNUSED,symbolS * to_symbol ATTRIBUTE_UNUSED)1061440a403fSchristos md_create_long_jump (char *ptr ATTRIBUTE_UNUSED,
1062440a403fSchristos addressT from_addr ATTRIBUTE_UNUSED,
1063440a403fSchristos addressT to_addr ATTRIBUTE_UNUSED,
1064440a403fSchristos fragS *frag ATTRIBUTE_UNUSED,
1065440a403fSchristos symbolS *to_symbol ATTRIBUTE_UNUSED)
1066440a403fSchristos {
1067440a403fSchristos }
1068440a403fSchristos
1069440a403fSchristos static int
set_cpu_model(const char * arg)1070440a403fSchristos set_cpu_model (const char *arg)
1071440a403fSchristos {
1072440a403fSchristos char buf[4];
1073440a403fSchristos char *model = buf;
1074440a403fSchristos
1075440a403fSchristos if (arg[0] == 'k')
1076440a403fSchristos arg++;
1077440a403fSchristos
1078440a403fSchristos *model++ = *arg++;
1079440a403fSchristos
1080440a403fSchristos if (strchr ("abdx", model[-1]) == NULL)
1081440a403fSchristos return 0;
1082440a403fSchristos
1083440a403fSchristos if (model[-1] == 'd')
1084440a403fSchristos {
1085440a403fSchristos if (arg[0] == 'f' || arg[0] == 'j')
1086440a403fSchristos model[-1] = *arg++;
1087440a403fSchristos }
1088440a403fSchristos else if (model[-1] == 'x')
1089440a403fSchristos {
1090440a403fSchristos if (arg[0] == 't')
1091440a403fSchristos model[-1] = *arg++;
1092440a403fSchristos }
1093440a403fSchristos
1094440a403fSchristos if (arg[0] == '-')
1095440a403fSchristos arg++;
1096440a403fSchristos
1097440a403fSchristos if (strncmp (arg, "11", 2) != 0)
1098440a403fSchristos return 0;
1099440a403fSchristos arg += 2;
1100440a403fSchristos
1101440a403fSchristos if (arg[0] == '-')
1102440a403fSchristos {
1103440a403fSchristos if (*++arg == 0)
1104440a403fSchristos return 0;
1105440a403fSchristos }
1106440a403fSchristos
1107440a403fSchristos /* Allow up to two revision letters. */
1108440a403fSchristos if (arg[0] != 0)
1109440a403fSchristos *model++ = *arg++;
1110440a403fSchristos if (arg[0] != 0)
1111440a403fSchristos *model++ = *arg++;
1112440a403fSchristos
1113440a403fSchristos *model++ = 0;
1114440a403fSchristos
1115440a403fSchristos set_option ("no-extensions");
1116440a403fSchristos
1117440a403fSchristos /* KA11 (11/15/20). */
1118440a403fSchristos if (strncmp (buf, "a", 1) == 0)
1119440a403fSchristos return 1; /* No extensions. */
1120440a403fSchristos
1121440a403fSchristos /* KB11 (11/45/50/55/70). */
1122440a403fSchristos else if (strncmp (buf, "b", 1) == 0)
1123440a403fSchristos return set_option ("eis") && set_option ("spl");
1124440a403fSchristos
1125440a403fSchristos /* KD11-A (11/35/40). */
1126440a403fSchristos else if (strncmp (buf, "da", 2) == 0)
1127440a403fSchristos return set_option ("limited-eis");
1128440a403fSchristos
1129440a403fSchristos /* KD11-B (11/05/10). */
1130440a403fSchristos else if (strncmp (buf, "db", 2) == 0
1131440a403fSchristos /* KD11-D (11/04). */
1132440a403fSchristos || strncmp (buf, "dd", 2) == 0)
1133440a403fSchristos return 1; /* no extensions */
1134440a403fSchristos
1135440a403fSchristos /* KD11-E (11/34). */
1136440a403fSchristos else if (strncmp (buf, "de", 2) == 0)
1137440a403fSchristos return set_option ("eis") && set_option ("mxps");
1138440a403fSchristos
1139440a403fSchristos /* KD11-F (11/03). */
1140440a403fSchristos else if (strncmp (buf, "df", 2) == 0
1141440a403fSchristos /* KD11-H (11/03). */
1142440a403fSchristos || strncmp (buf, "dh", 2) == 0
1143440a403fSchristos /* KD11-Q (11/03). */
1144440a403fSchristos || strncmp (buf, "dq", 2) == 0)
1145440a403fSchristos return set_option ("limited-eis") && set_option ("mxps");
1146440a403fSchristos
1147440a403fSchristos /* KD11-K (11/60). */
1148440a403fSchristos else if (strncmp (buf, "dk", 2) == 0)
1149440a403fSchristos return set_option ("eis")
1150440a403fSchristos && set_option ("mxps")
1151440a403fSchristos && set_option ("ucode");
1152440a403fSchristos
1153440a403fSchristos /* KD11-Z (11/44). */
1154440a403fSchristos else if (strncmp (buf, "dz", 2) == 0)
1155440a403fSchristos return set_option ("csm")
1156440a403fSchristos && set_option ("eis")
1157440a403fSchristos && set_option ("mfpt")
1158440a403fSchristos && set_option ("mxps")
1159440a403fSchristos && set_option ("spl");
1160440a403fSchristos
1161440a403fSchristos /* F11 (11/23/24). */
1162440a403fSchristos else if (strncmp (buf, "f", 1) == 0)
1163440a403fSchristos return set_option ("eis")
1164440a403fSchristos && set_option ("mfpt")
1165440a403fSchristos && set_option ("mxps");
1166440a403fSchristos
1167440a403fSchristos /* J11 (11/53/73/83/84/93/94). */
1168440a403fSchristos else if (strncmp (buf, "j", 1) == 0)
1169440a403fSchristos return set_option ("csm")
1170440a403fSchristos && set_option ("eis")
1171440a403fSchristos && set_option ("mfpt")
1172440a403fSchristos && set_option ("multiproc")
1173440a403fSchristos && set_option ("mxps")
1174440a403fSchristos && set_option ("spl");
1175440a403fSchristos
1176440a403fSchristos /* T11 (11/21). */
1177440a403fSchristos else if (strncmp (buf, "t", 1) == 0)
1178440a403fSchristos return set_option ("limited-eis")
1179440a403fSchristos && set_option ("mxps");
1180440a403fSchristos
1181440a403fSchristos else
1182440a403fSchristos return 0;
1183440a403fSchristos }
1184440a403fSchristos
1185440a403fSchristos static int
set_machine_model(const char * arg)1186440a403fSchristos set_machine_model (const char *arg)
1187440a403fSchristos {
1188440a403fSchristos if (strncmp (arg, "pdp-11/", 7) != 0
1189440a403fSchristos && strncmp (arg, "pdp11/", 6) != 0
1190440a403fSchristos && strncmp (arg, "11/", 3) != 0)
1191440a403fSchristos return 0;
1192440a403fSchristos
1193440a403fSchristos if (strncmp (arg, "pdp", 3) == 0)
1194440a403fSchristos arg += 3;
1195440a403fSchristos if (arg[0] == '-')
1196440a403fSchristos arg++;
1197440a403fSchristos if (strncmp (arg, "11/", 3) == 0)
1198440a403fSchristos arg += 3;
1199440a403fSchristos
1200440a403fSchristos if (strcmp (arg, "03") == 0)
1201440a403fSchristos return set_cpu_model ("kd11f");
1202440a403fSchristos
1203440a403fSchristos else if (strcmp (arg, "04") == 0)
1204440a403fSchristos return set_cpu_model ("kd11d");
1205440a403fSchristos
1206440a403fSchristos else if (strcmp (arg, "05") == 0
1207440a403fSchristos || strcmp (arg, "10") == 0)
1208440a403fSchristos return set_cpu_model ("kd11b");
1209440a403fSchristos
1210440a403fSchristos else if (strcmp (arg, "15") == 0
1211440a403fSchristos || strcmp (arg, "20") == 0)
1212440a403fSchristos return set_cpu_model ("ka11");
1213440a403fSchristos
1214440a403fSchristos else if (strcmp (arg, "21") == 0)
1215440a403fSchristos return set_cpu_model ("t11");
1216440a403fSchristos
1217440a403fSchristos else if (strcmp (arg, "23") == 0
1218440a403fSchristos || strcmp (arg, "24") == 0)
1219440a403fSchristos return set_cpu_model ("f11");
1220440a403fSchristos
1221440a403fSchristos else if (strcmp (arg, "34") == 0
1222440a403fSchristos || strcmp (arg, "34a") == 0)
1223440a403fSchristos return set_cpu_model ("kd11e");
1224440a403fSchristos
1225440a403fSchristos else if (strcmp (arg, "35") == 0
1226440a403fSchristos || strcmp (arg, "40") == 0)
1227440a403fSchristos return set_cpu_model ("kd11da");
1228440a403fSchristos
1229440a403fSchristos else if (strcmp (arg, "44") == 0)
1230440a403fSchristos return set_cpu_model ("kd11dz");
1231440a403fSchristos
1232440a403fSchristos else if (strcmp (arg, "45") == 0
1233440a403fSchristos || strcmp (arg, "50") == 0
1234440a403fSchristos || strcmp (arg, "55") == 0
1235440a403fSchristos || strcmp (arg, "70") == 0)
1236440a403fSchristos return set_cpu_model ("kb11");
1237440a403fSchristos
1238440a403fSchristos else if (strcmp (arg, "60") == 0)
1239440a403fSchristos return set_cpu_model ("kd11k");
1240440a403fSchristos
1241440a403fSchristos else if (strcmp (arg, "53") == 0
1242440a403fSchristos || strcmp (arg, "73") == 0
1243440a403fSchristos || strcmp (arg, "83") == 0
1244440a403fSchristos || strcmp (arg, "84") == 0
1245440a403fSchristos || strcmp (arg, "93") == 0
1246440a403fSchristos || strcmp (arg, "94") == 0)
1247440a403fSchristos return set_cpu_model ("j11")
1248440a403fSchristos && set_option ("fpp");
1249440a403fSchristos
1250440a403fSchristos else
1251440a403fSchristos return 0;
1252440a403fSchristos }
1253440a403fSchristos
1254440a403fSchristos const char *md_shortopts = "m:";
1255440a403fSchristos
1256440a403fSchristos struct option md_longopts[] =
1257440a403fSchristos {
1258440a403fSchristos #define OPTION_CPU 257
1259440a403fSchristos { "cpu", required_argument, NULL, OPTION_CPU },
1260440a403fSchristos #define OPTION_MACHINE 258
1261440a403fSchristos { "machine", required_argument, NULL, OPTION_MACHINE },
1262440a403fSchristos #define OPTION_PIC 259
1263440a403fSchristos { "pic", no_argument, NULL, OPTION_PIC },
1264440a403fSchristos { NULL, no_argument, NULL, 0 }
1265440a403fSchristos };
1266440a403fSchristos
1267440a403fSchristos size_t md_longopts_size = sizeof (md_longopts);
1268440a403fSchristos
1269440a403fSchristos /* Invocation line includes a switch not recognized by the base assembler.
1270440a403fSchristos See if it's a processor-specific option. */
1271440a403fSchristos
1272440a403fSchristos int
md_parse_option(int c,const char * arg)1273440a403fSchristos md_parse_option (int c, const char *arg)
1274440a403fSchristos {
1275440a403fSchristos init_defaults ();
1276440a403fSchristos
1277440a403fSchristos switch (c)
1278440a403fSchristos {
1279440a403fSchristos case 'm':
1280440a403fSchristos if (set_option (arg))
1281440a403fSchristos return 1;
1282440a403fSchristos if (set_cpu_model (arg))
1283440a403fSchristos return 1;
1284440a403fSchristos if (set_machine_model (arg))
1285440a403fSchristos return 1;
1286440a403fSchristos break;
1287440a403fSchristos
1288440a403fSchristos case OPTION_CPU:
1289440a403fSchristos if (set_cpu_model (arg))
1290440a403fSchristos return 1;
1291440a403fSchristos break;
1292440a403fSchristos
1293440a403fSchristos case OPTION_MACHINE:
1294440a403fSchristos if (set_machine_model (arg))
1295440a403fSchristos return 1;
1296440a403fSchristos break;
1297440a403fSchristos
1298440a403fSchristos case OPTION_PIC:
1299440a403fSchristos if (set_option ("pic"))
1300440a403fSchristos return 1;
1301440a403fSchristos break;
1302440a403fSchristos
1303440a403fSchristos default:
1304440a403fSchristos break;
1305440a403fSchristos }
1306440a403fSchristos
1307440a403fSchristos return 0;
1308440a403fSchristos }
1309440a403fSchristos
1310440a403fSchristos void
md_show_usage(FILE * stream)1311440a403fSchristos md_show_usage (FILE *stream)
1312440a403fSchristos {
1313440a403fSchristos fprintf (stream, "\
1314440a403fSchristos \n\
131506324dcfSchristos PDP-11 instruction set extensions:\n\
1316440a403fSchristos \n\
131706324dcfSchristos -m(no-)cis allow (disallow) commercial instruction set\n\
1318440a403fSchristos -m(no-)csm allow (disallow) CSM instruction\n\
1319440a403fSchristos -m(no-)eis allow (disallow) full extended instruction set\n\
1320440a403fSchristos -m(no-)fis allow (disallow) KEV11 floating-point instructions\n\
1321440a403fSchristos -m(no-)fpp allow (disallow) FP-11 floating-point instructions\n\
1322440a403fSchristos -m(no-)fpu allow (disallow) FP-11 floating-point instructions\n\
1323440a403fSchristos -m(no-)limited-eis allow (disallow) limited extended instruction set\n\
1324440a403fSchristos -m(no-)mfpt allow (disallow) processor type instruction\n\
1325440a403fSchristos -m(no-)multiproc allow (disallow) multiprocessor instructions\n\
1326440a403fSchristos -m(no-)mxps allow (disallow) processor status instructions\n\
1327440a403fSchristos -m(no-)spl allow (disallow) SPL instruction\n\
1328440a403fSchristos -m(no-)ucode allow (disallow) microcode instructions\n\
1329440a403fSchristos -mall-extensions allow all instruction set extensions\n\
1330440a403fSchristos (this is the default)\n\
133106324dcfSchristos -mno-extensions disallow all instruction set extensions\n\
133206324dcfSchristos -pic generate position-independent code\n\
1333440a403fSchristos \n\
1334440a403fSchristos PDP-11 CPU model options:\n\
1335440a403fSchristos \n\
1336440a403fSchristos -mka11* KA11 CPU. base line instruction set only\n\
1337440a403fSchristos -mkb11* KB11 CPU. enable full EIS and SPL\n\
1338440a403fSchristos -mkd11a* KD11-A CPU. enable limited EIS\n\
1339440a403fSchristos -mkd11b* KD11-B CPU. base line instruction set only\n\
1340440a403fSchristos -mkd11d* KD11-D CPU. base line instruction set only\n\
1341440a403fSchristos -mkd11e* KD11-E CPU. enable full EIS, MTPS, and MFPS\n\
1342440a403fSchristos -mkd11f* KD11-F CPU. enable limited EIS, MTPS, and MFPS\n\
1343440a403fSchristos -mkd11h* KD11-H CPU. enable limited EIS, MTPS, and MFPS\n\
1344440a403fSchristos -mkd11q* KD11-Q CPU. enable limited EIS, MTPS, and MFPS\n\
1345440a403fSchristos -mkd11k* KD11-K CPU. enable full EIS, MTPS, MFPS, LDUB, MED,\n\
1346440a403fSchristos XFC, and MFPT\n\
1347440a403fSchristos -mkd11z* KD11-Z CPU. enable full EIS, MTPS, MFPS, MFPT, SPL,\n\
1348440a403fSchristos and CSM\n\
1349440a403fSchristos -mf11* F11 CPU. enable full EIS, MFPS, MTPS, and MFPT\n\
1350440a403fSchristos -mj11* J11 CPU. enable full EIS, MTPS, MFPS, MFPT, SPL,\n\
1351440a403fSchristos CSM, TSTSET, and WRTLCK\n\
1352440a403fSchristos -mt11* T11 CPU. enable limited EIS, MTPS, and MFPS\n\
1353440a403fSchristos \n\
1354440a403fSchristos PDP-11 machine model options:\n\
1355440a403fSchristos \n\
1356440a403fSchristos -m11/03 same as -mkd11f\n\
1357440a403fSchristos -m11/04 same as -mkd11d\n\
1358440a403fSchristos -m11/05 same as -mkd11b\n\
1359440a403fSchristos -m11/10 same as -mkd11b\n\
1360440a403fSchristos -m11/15 same as -mka11\n\
1361440a403fSchristos -m11/20 same as -mka11\n\
1362440a403fSchristos -m11/21 same as -mt11\n\
1363440a403fSchristos -m11/23 same as -mf11\n\
1364440a403fSchristos -m11/24 same as -mf11\n\
1365440a403fSchristos -m11/34 same as -mkd11e\n\
1366440a403fSchristos -m11/34a same as -mkd11e -mfpp\n\
1367440a403fSchristos -m11/35 same as -mkd11a\n\
1368440a403fSchristos -m11/40 same as -mkd11a\n\
1369440a403fSchristos -m11/44 same as -mkd11z\n\
1370440a403fSchristos -m11/45 same as -mkb11\n\
1371440a403fSchristos -m11/50 same as -mkb11\n\
1372440a403fSchristos -m11/53 same as -mj11\n\
1373440a403fSchristos -m11/55 same as -mkb11\n\
1374440a403fSchristos -m11/60 same as -mkd11k\n\
1375440a403fSchristos -m11/70 same as -mkb11\n\
1376440a403fSchristos -m11/73 same as -mj11\n\
1377440a403fSchristos -m11/83 same as -mj11\n\
1378440a403fSchristos -m11/84 same as -mj11\n\
1379440a403fSchristos -m11/93 same as -mj11\n\
1380440a403fSchristos -m11/94 same as -mj11\n\
1381440a403fSchristos ");
1382440a403fSchristos }
1383440a403fSchristos
1384440a403fSchristos symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1385440a403fSchristos md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1386440a403fSchristos {
1387440a403fSchristos return 0;
1388440a403fSchristos }
1389440a403fSchristos
1390440a403fSchristos valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT size)1391440a403fSchristos md_section_align (segT segment ATTRIBUTE_UNUSED,
1392440a403fSchristos valueT size)
1393440a403fSchristos {
1394440a403fSchristos return (size + 1) & ~1;
1395440a403fSchristos }
1396440a403fSchristos
1397440a403fSchristos long
md_pcrel_from(fixS * fixP)1398440a403fSchristos md_pcrel_from (fixS *fixP)
1399440a403fSchristos {
1400440a403fSchristos return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
1401440a403fSchristos }
1402440a403fSchristos
1403440a403fSchristos /* Translate internal representation of relocation info to BFD target
1404440a403fSchristos format. */
1405440a403fSchristos
1406440a403fSchristos arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)1407440a403fSchristos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1408440a403fSchristos fixS *fixp)
1409440a403fSchristos {
1410440a403fSchristos arelent *reloc;
1411440a403fSchristos bfd_reloc_code_real_type code;
1412440a403fSchristos
1413440a403fSchristos reloc = XNEW (arelent);
1414440a403fSchristos
1415440a403fSchristos reloc->sym_ptr_ptr = XNEW (asymbol *);
1416440a403fSchristos *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1417440a403fSchristos reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1418440a403fSchristos
1419440a403fSchristos /* This is taken account for in md_apply_fix(). */
1420440a403fSchristos reloc->addend = -symbol_get_bfdsym (fixp->fx_addsy)->section->vma;
1421440a403fSchristos
1422440a403fSchristos switch (fixp->fx_r_type)
1423440a403fSchristos {
1424440a403fSchristos case BFD_RELOC_16:
1425440a403fSchristos if (fixp->fx_pcrel)
1426440a403fSchristos code = BFD_RELOC_16_PCREL;
1427440a403fSchristos else
1428440a403fSchristos code = BFD_RELOC_16;
1429440a403fSchristos break;
1430440a403fSchristos
1431440a403fSchristos case BFD_RELOC_16_PCREL:
1432440a403fSchristos code = BFD_RELOC_16_PCREL;
1433440a403fSchristos break;
1434440a403fSchristos
1435440a403fSchristos default:
1436440a403fSchristos BAD_CASE (fixp->fx_r_type);
1437440a403fSchristos return NULL;
1438440a403fSchristos }
1439440a403fSchristos
1440440a403fSchristos reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1441440a403fSchristos
1442440a403fSchristos if (reloc->howto == NULL)
1443440a403fSchristos {
1444440a403fSchristos as_bad_where (fixp->fx_file, fixp->fx_line,
1445440a403fSchristos _("Can not represent %s relocation in this object file format"),
1446440a403fSchristos bfd_get_reloc_code_name (code));
1447440a403fSchristos return NULL;
1448440a403fSchristos }
1449440a403fSchristos
1450440a403fSchristos return reloc;
1451440a403fSchristos }
1452440a403fSchristos
1453440a403fSchristos void
pseudo_bss(int c ATTRIBUTE_UNUSED)1454440a403fSchristos pseudo_bss (int c ATTRIBUTE_UNUSED)
1455440a403fSchristos {
1456440a403fSchristos int temp;
1457440a403fSchristos
1458440a403fSchristos temp = get_absolute_expression ();
1459440a403fSchristos subseg_set (bss_section, temp);
1460440a403fSchristos demand_empty_rest_of_line ();
1461440a403fSchristos }
1462440a403fSchristos
1463440a403fSchristos void
pseudo_even(int c ATTRIBUTE_UNUSED)1464440a403fSchristos pseudo_even (int c ATTRIBUTE_UNUSED)
1465440a403fSchristos {
1466440a403fSchristos int alignment = 1; /* 2^1 */
1467440a403fSchristos frag_align (alignment, 0, 1);
1468440a403fSchristos record_alignment (now_seg, alignment);
1469440a403fSchristos }
1470440a403fSchristos
1471440a403fSchristos const char *
md_atof(int type,char * litP,int * sizeP)1472440a403fSchristos md_atof (int type, char * litP, int * sizeP)
1473440a403fSchristos {
1474440a403fSchristos return vax_md_atof (type, litP, sizeP);
1475440a403fSchristos }
1476