1 /* Definitions of target machine for GNU compiler.
2 For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
3 Copyright (C) 1990, 1993 Free Software Foundation, Inc.
4 Written by Robert Andersson (ra@intsys.no), International Systems,
7 This file outputs assembler source suitable for the native Tower as
8 and with sdb debugging symbols. See tower.h for more comments.
10 This file was based on m68k.h, hp320.h and 3b1.h as of the 1.37.1 version.
12 This file is part of GNU CC.
14 GNU CC is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
19 GNU CC is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GNU CC; see the file COPYING. If not, write to
26 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
29 #include "m68k/tower.h"
30 #undef SELECT_RTX_SECTION
32 /* Use default settings for system V.3. */
36 /* Names to predefine in the preprocessor for this target machine. */
38 #define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600 -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
40 /* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
41 This will control the use of inline 68881 insns in certain macros.
42 Also, define special define used to identify the Tower assembler. */
44 #define CPP_SPEC "-D__TOWER_ASM__ %{m68881:-D__HAVE_68881__}"
46 /* We don't want local labels to start with period.
47 See ASM_OUTPUT_INTERNAL_LABEL. */
48 #undef LOCAL_LABEL_PREFIX
49 #define LOCAL_LABEL_PREFIX ""
51 /* These four macros control how m68k.md is expanded. */
53 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
54 #define SGS /* Uses SGS assembler */
55 #define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
56 #define SGS_NO_LI /* Suppress jump table label usage */
58 /* Turn on SDB debugging info. */
60 #define SDB_DEBUGGING_INFO
62 /* This is only useful if gdb is changed, but doesn't harm anyway. */
64 #define ASM_IDENTIFY_GCC(FILE) \
65 fprintf (FILE, "gcc2_compiled%%:\n")
67 /* All the ASM_OUTPUT macros need to conform to the Tower as syntax. */
69 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
71 fprintf (FILE, "\tfile\t"); \
72 output_quoted_string (FILE, FILENAME); \
73 fprintf (FILE, "\n"); \
74 fprintf (FILE, "section ~init,\"x\"\n"); \
75 fprintf (FILE, "section ~fini,\"x\"\n"); \
76 fprintf (FILE, "section ~rodata,\"x\"\n"); \
77 fprintf (FILE, "text\n"); \
80 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
81 fprintf (FILE, "\tln\t%d\n", \
82 (sdb_begin_function_line \
83 ? last_linenum - sdb_begin_function_line : 1))
85 #undef ASM_OUTPUT_IDENT
86 #define ASM_OUTPUT_IDENT(FILE, NAME) \
87 fprintf (FILE, "\tident\t\"%s\" \n", NAME)
89 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
90 do { register int sp = 0, lp = 0; \
91 fprintf ((FILE), "\tbyte\t"); \
93 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
95 fprintf ((FILE), "'%c", (PTR)[sp]); } \
98 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
102 fprintf ((FILE), "\n\tbyte\t"); } \
104 putc (',', (FILE)); \
106 putc ('\n', (FILE)); } while (0)
108 /* Translate Motorola opcodes such as `jbeq'
109 into SGS/Tower opcodes such as `beq.w'.
110 Change `move' to `mov'.
111 Change `cmpm' to `cmp'.
112 Change `divsl' to `tdivs'.
113 Change `divul' to `tdivu'.
114 Change `ftst' to `ftest'.
115 Change `fmove' to `fmov'. */
117 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
118 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
120 while (*(PTR) != ' ') \
121 { putc (*(PTR), (FILE)); ++(PTR); } \
122 fprintf ((FILE), ".w"); } \
123 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
124 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
125 { fprintf ((FILE), "mov"); (PTR) += 4; } \
126 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
127 && (PTR)[2] == 'p' && (PTR)[3] == 'm') \
128 { fprintf ((FILE), "cmp"); (PTR) += 4; } \
129 else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
130 && (PTR)[2] == 'v' && (PTR)[3] == 's' \
131 && (PTR)[4] == 'l') \
132 { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
133 else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
134 && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
135 && (PTR)[4] == 'l') \
136 { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
137 else if ((PTR)[0] == 'f' && (PTR)[1] == 't' \
138 && (PTR)[2] == 's' && (PTR)[3] == 't') \
139 { fprintf ((FILE), "ftest"); (PTR) += 4; } \
140 else if ((PTR)[0] == 'f' && (PTR)[1] == 'm' \
141 && (PTR)[2] == 'o' && (PTR)[3] == 'v' \
142 && (PTR)[4] == 'e') \
143 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
148 /* Override parts of m68k.h to fit the Tower assembler.
149 This section needs to track changes done to m68k.h in the future. */
151 #undef TARGET_VERSION
152 #define TARGET_VERSION fprintf (stderr, " (68k, Motorola/SGS/Tower32 syntax)");
154 #undef FUNCTION_BLOCK_PROFILER
155 #define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
157 char label1[20], label2[20]; \
158 ASM_GENERATE_INTERNAL_LABEL (label1, "LPBX", 0); \
159 ASM_GENERATE_INTERNAL_LABEL (label2, "LPI", LABELNO); \
160 fprintf (FILE, "\ttst.l %s\n\tbne %s\n\tpea %s\n\tjsr __bb_init_func\n\taddq.l &4,%%sp\n", \
161 label1, label2, label1); \
162 ASM_OUTPUT_INTERNAL_LABEL (FILE, "LPI", LABELNO); \
166 #undef BLOCK_PROFILER
167 #define BLOCK_PROFILER(FILE, BLOCKNO) \
170 ASM_GENERATE_INTERNAL_LABEL (label, "LPBX", 2); \
171 fprintf (FILE, "\taddq.l &1,%s+%d\n", label, 4 * BLOCKNO); \
174 #undef FUNCTION_PROFILER
175 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
176 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
178 /* The prologue is identical to the one in m68k.h except that the
179 assembler syntax is different. */
181 #undef FUNCTION_PROLOGUE
182 #define FUNCTION_PROLOGUE(FILE, SIZE) \
183 { register int regno; \
184 register int mask = 0; \
185 extern char call_used_regs[]; \
186 int fsize = ((SIZE) + 3) & -4; \
187 if (frame_pointer_needed) \
188 { if (TARGET_68020 || fsize < 0x8000) \
189 fprintf (FILE, "\tlink %%a6,&%d\n", -fsize); \
191 fprintf (FILE, "\tlink %%a6,&0\n\tsub.l &%d,%%sp\n", fsize); } \
192 for (regno = 16; regno < 24; regno++) \
193 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
194 mask |= 1 << (regno - 16); \
195 if ((mask & 0xff) != 0) \
196 fprintf (FILE, "\tfmovm &0x%x,-(%%sp)\n", mask & 0xff); \
198 for (regno = 0; regno < 16; regno++) \
199 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
200 mask |= 1 << (15 - regno); \
201 if (frame_pointer_needed) \
202 mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
203 if (exact_log2 (mask) >= 0) \
204 fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[15 - exact_log2 (mask)]); \
205 else if (mask) fprintf (FILE, "\tmovm.l &0x%x,-(%%sp)\n", mask); }
207 /* The epilogue is identical to the one in m68k.h except that:
208 a) The assembler syntax is different.
209 b) Pointers are returned both in %d0 and %a0.
210 c) FUNCTION_EXTRA_EPILOGUE is not needed. */
212 #undef FUNCTION_EPILOGUE
213 #define FUNCTION_EPILOGUE(FILE, SIZE) \
214 { register int regno; \
215 register int mask, fmask; \
216 register int nregs; \
217 int offset, foffset; \
218 extern char call_used_regs[]; \
219 int fsize = ((SIZE) + 3) & -4; \
221 nregs = 0; fmask = 0; \
222 for (regno = 16; regno < 24; regno++) \
223 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
224 { nregs++; fmask |= 1 << (23 - regno); } \
225 foffset = nregs * 12; \
226 nregs = 0; mask = 0; \
227 if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
228 for (regno = 0; regno < 16; regno++) \
229 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
230 { nregs++; mask |= 1 << regno; } \
231 offset = foffset + nregs * 4; \
232 if (offset + fsize >= 0x8000 \
233 && frame_pointer_needed \
234 && (mask || fmask)) \
235 { fprintf (FILE, "\tmov.l &%d,%%a0\n", -fsize); \
236 fsize = 0, big = 1; } \
237 if (exact_log2 (mask) >= 0) { \
239 fprintf (FILE, "\tmov.l -%d(%%a6,%%a0.l),%s\n", \
240 offset + fsize, reg_names[exact_log2 (mask)]); \
241 else if (! frame_pointer_needed) \
242 fprintf (FILE, "\tmov.l (%%sp)+,%s\n", \
243 reg_names[exact_log2 (mask)]); \
245 fprintf (FILE, "\tmov.l -%d(%%a6),%s\n", \
246 offset + fsize, reg_names[exact_log2 (mask)]); } \
249 fprintf (FILE, "\tmovm.l -%d(%%a6,%%a0.l),&0x%x\n", \
250 offset + fsize, mask); \
251 else if (! frame_pointer_needed) \
252 fprintf (FILE, "\tmovm.l (%%sp)+,&0x%x\n", mask); \
254 fprintf (FILE, "\tmovm.l -%d(%%a6),&0x%x\n", \
255 offset + fsize, mask); } \
258 fprintf (FILE, "\tfmovm -%d(%%a6,%%a0.l),&0x%x\n", \
259 foffset + fsize, fmask); \
260 else if (! frame_pointer_needed) \
261 fprintf (FILE, "\tfmovm (%%sp)+,&0x%x\n", fmask); \
263 fprintf (FILE, "\tfmovm -%d(%%a6),&0x%x\n", \
264 foffset + fsize, fmask); } \
265 if (current_function_returns_pointer) \
266 fprintf (FILE, "\tmov.l %%d0,%%a0\n"); \
267 if (frame_pointer_needed) \
268 fprintf (FILE, "\tunlk %%a6\n"); \
269 if (current_function_pops_args) \
270 fprintf (FILE, "\trtd &%d\n", current_function_pops_args); \
271 else fprintf (FILE, "\trts\n"); }
273 /* This is how to output an insn to push a register on the stack.
274 It need not be very fast code. */
276 #undef ASM_OUTPUT_REG_PUSH
277 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
278 fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
280 /* This is how to output an insn to pop a register from the stack.
281 It need not be very fast code. */
283 #undef ASM_OUTPUT_REG_POP
284 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
285 fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
287 #undef ASM_FILE_START
288 #define ASM_FILE_START(FILE) \
289 ( fprintf (FILE, "#NO_APP\n"), \
290 output_file_directive ((FILE), main_input_filename))
292 #undef TEXT_SECTION_ASM_OP
293 #define TEXT_SECTION_ASM_OP "text"
295 #undef DATA_SECTION_ASM_OP
296 #define DATA_SECTION_ASM_OP "data"
298 /* This says how to output an assembler line to define a global common symbol.
299 We use SIZE rather than ROUNDED, as this is what the native cc does. */
301 #undef ASM_OUTPUT_COMMON
302 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
303 ( fputs ("\tcomm ", (FILE)), \
304 assemble_name ((FILE), (NAME)), \
305 fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
307 /* This says how to output an assembler line to define a local common symbol.
308 We use SIZE rather than ROUNDED, as this is what the native cc does. */
310 #undef ASM_OUTPUT_LOCAL
311 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
312 ( fputs ("\tlcomm ", (FILE)), \
313 assemble_name ((FILE), (NAME)), \
314 fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
316 /* Store in OUTPUT a string (made with alloca) containing
317 an assembler-name for a local static variable named NAME.
318 LABELNO is an integer which is different for each call. */
320 #undef ASM_FORMAT_PRIVATE_NAME
321 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
322 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 11), \
323 sprintf ((OUTPUT), "%s%%%%%d", (NAME), (LABELNO)))
325 /* This is the command to make the user-level label named NAME
326 defined for reference from other files. */
329 #define GLOBAL_ASM_OP "global"
331 #undef ASM_GENERATE_INTERNAL_LABEL
332 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
333 sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
335 #undef ASM_OUTPUT_INTERNAL_LABEL
336 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
337 fprintf ((FILE), "%s%%%d:\n", (PREFIX), (NUM))
339 #undef ASM_OUTPUT_CASE_LABEL
340 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
341 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
342 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
344 #undef ASM_OUTPUT_DOUBLE
345 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
347 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
348 fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
351 #undef ASM_OUTPUT_LONG_DOUBLE
352 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
354 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
355 fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
358 #undef ASM_OUTPUT_FLOAT
359 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
361 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
362 fprintf ((FILE), "\tlong 0x%x\n", l); \
365 /* This is how to output an assembler line defining an `int' constant. */
367 #undef ASM_OUTPUT_INT
368 #define ASM_OUTPUT_INT(FILE,VALUE) \
369 ( fprintf (FILE, "\tlong "), \
370 output_addr_const (FILE, (VALUE)), \
371 fprintf (FILE, "\n"))
373 /* Likewise for `char' and `short' constants. */
375 #undef ASM_OUTPUT_SHORT
376 #define ASM_OUTPUT_SHORT(FILE,VALUE) \
377 ( fprintf (FILE, "\tshort "), \
378 output_addr_const (FILE, (VALUE)), \
379 fprintf (FILE, "\n"))
381 #undef ASM_OUTPUT_CHAR
382 #define ASM_OUTPUT_CHAR(FILE,VALUE) \
383 ( fprintf (FILE, "\tbyte "), \
384 output_addr_const (FILE, (VALUE)), \
385 fprintf (FILE, "\n"))
387 /* This is how to output an assembler line for a numeric constant byte. */
389 #undef ASM_OUTPUT_BYTE
390 #define ASM_OUTPUT_BYTE(FILE,VALUE) \
391 fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
393 #undef ASM_OUTPUT_ADDR_VEC_ELT
394 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
395 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
397 #undef ASM_OUTPUT_ADDR_DIFF_ELT
398 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
399 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
401 #undef ASM_OUTPUT_ALIGN
402 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
404 fprintf (FILE, "\teven\n"); \
405 else if ((LOG) != 0) \
408 #undef ASM_OUTPUT_SKIP
409 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
410 fprintf (FILE, "\tspace %d\n", (SIZE))
413 #define PRINT_OPERAND(FILE, X, CODE) \
414 { if (CODE == '.') fprintf (FILE, "."); \
415 else if (CODE == '#') fprintf (FILE, "&"); \
416 else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
417 else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
418 else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
419 else if (CODE == '!') fprintf (FILE, "%%fpcr"); \
420 else if (CODE == '/') \
421 fprintf (FILE, "%%"); \
422 else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
423 else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
424 else if (GET_CODE (X) == REG) \
425 fprintf (FILE, "%s", reg_names[REGNO (X)]); \
426 else if (GET_CODE (X) == MEM) \
427 output_address (XEXP (X, 0)); \
428 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
429 { REAL_VALUE_TYPE r; long l; \
430 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
431 REAL_VALUE_TO_TARGET_SINGLE (r, l); \
432 fprintf (FILE, "&0x%x", l); } \
433 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
434 { REAL_VALUE_TYPE r; int i[2]; \
435 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
436 REAL_VALUE_TO_TARGET_DOUBLE (r, i); \
437 fprintf (FILE, "&0x%x%08x", i[0], i[1]); } \
438 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
439 { REAL_VALUE_TYPE r; \
440 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
441 ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
442 else { putc ('&', FILE); output_addr_const (FILE, X); }}
444 /* Note that this contains a kludge that knows that the only reason
445 we have an address (plus (label_ref...) (reg...))
446 is in the insn before a tablejump, and we know that the table is
447 exactly 10 bytes away. */
449 #undef PRINT_OPERAND_ADDRESS
450 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
451 { register rtx reg1, reg2, breg, ireg; \
452 register rtx addr = ADDR; \
454 switch (GET_CODE (addr)) \
457 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
460 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
463 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
466 reg1 = 0; reg2 = 0; \
467 ireg = 0; breg = 0; \
469 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
471 offset = XEXP (addr, 0); \
472 addr = XEXP (addr, 1); \
474 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
476 offset = XEXP (addr, 1); \
477 addr = XEXP (addr, 0); \
479 if (GET_CODE (addr) != PLUS) ; \
480 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
482 reg1 = XEXP (addr, 0); \
483 addr = XEXP (addr, 1); \
485 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
487 reg1 = XEXP (addr, 1); \
488 addr = XEXP (addr, 0); \
490 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
492 reg1 = XEXP (addr, 0); \
493 addr = XEXP (addr, 1); \
495 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
497 reg1 = XEXP (addr, 1); \
498 addr = XEXP (addr, 0); \
500 else if (GET_CODE (XEXP (addr, 0)) == REG) \
502 reg1 = XEXP (addr, 0); \
503 addr = XEXP (addr, 1); \
505 else if (GET_CODE (XEXP (addr, 1)) == REG) \
507 reg1 = XEXP (addr, 1); \
508 addr = XEXP (addr, 0); \
510 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
511 || GET_CODE (addr) == SIGN_EXTEND) \
512 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
513 /* for OLD_INDEXING \
514 else if (GET_CODE (addr) == PLUS) \
516 if (GET_CODE (XEXP (addr, 0)) == REG) \
518 reg2 = XEXP (addr, 0); \
519 addr = XEXP (addr, 1); \
521 else if (GET_CODE (XEXP (addr, 1)) == REG) \
523 reg2 = XEXP (addr, 1); \
524 addr = XEXP (addr, 0); \
528 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
529 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
530 || GET_CODE (reg1) == MULT)) \
531 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
532 { breg = reg2; ireg = reg1; } \
533 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
534 { breg = reg1; ireg = reg2; } \
535 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
537 if (GET_CODE (ireg) == MULT) \
538 { scale = INTVAL (XEXP (ireg, 1)); \
539 ireg = XEXP (ireg, 0); } \
540 if (GET_CODE (ireg) == SIGN_EXTEND) \
541 fprintf (FILE, "10(%%pc,%s.w", \
542 reg_names[REGNO (XEXP (ireg, 0))]); \
544 fprintf (FILE, "10(%%pc,%s.l", \
545 reg_names[REGNO (ireg)]); \
546 if (scale != 1) fprintf (FILE, "*%d", scale); \
549 if (ireg != 0 || breg != 0) \
554 output_addr_const (FILE, addr); \
555 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
558 if (ireg != 0 && GET_CODE (ireg) == MULT) \
559 { scale = INTVAL (XEXP (ireg, 1)); \
560 ireg = XEXP (ireg, 0); } \
561 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
562 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
563 else if (ireg != 0) \
564 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
565 if (scale != 1) fprintf (FILE, "*%d", scale); \
569 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
570 { fprintf (FILE, "10(%%pc,%s.w)", \
571 reg_names[REGNO (reg1)]); \
574 output_addr_const (FILE, addr); \
579 /* Override usual definitions of SDB output macros.
580 These definitions differ only in the absence of the period
581 at the beginning of the name of the directive
582 and in the use of `~' as the symbol for the current location. */
584 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
585 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
586 #define PUT_SDB_VAL(a) \
587 ( fputs ("\tval\t", asm_out_file), \
588 output_addr_const (asm_out_file, (a)), \
589 fputc (';', asm_out_file))
591 #define PUT_SDB_DEF(a) \
592 do { fprintf (asm_out_file, "\tdef\t"); \
593 ASM_OUTPUT_LABELREF (asm_out_file, a); \
594 fprintf (asm_out_file, ";"); } while (0)
596 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
597 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
598 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
599 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
600 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
601 #define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
602 #define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
604 #define PUT_SDB_TAG(a) \
605 do { fprintf (asm_out_file, "\ttag\t"); \
606 ASM_OUTPUT_LABELREF (asm_out_file, a); \
607 fprintf (asm_out_file, ";"); } while (0)
609 #define PUT_SDB_BLOCK_START(LINE) \
610 fprintf (asm_out_file, \
611 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
614 #define PUT_SDB_BLOCK_END(LINE) \
615 fprintf (asm_out_file, \
616 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
619 #define PUT_SDB_FUNCTION_START(LINE) \
620 fprintf (asm_out_file, \
621 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
624 #define PUT_SDB_FUNCTION_END(LINE) \
625 fprintf (asm_out_file, \
626 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
629 #define PUT_SDB_EPILOGUE_END(NAME) \
630 fprintf (asm_out_file, \
631 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
634 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
635 sprintf ((BUFFER), "~%dfake", (NUMBER));
637 #define NO_DOLLAR_IN_LABEL
638 #define NO_DOT_IN_LABEL
640 /* The usual definitions don't work because neither $ nor . is allowed. */
641 #define CONSTRUCTOR_NAME_FORMAT "_GLOBAL_%%I\%%%s"
643 /* Define a few machine-specific details
644 of the implementation of constructors.
646 The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN
647 and CTOR_LIST_END to contribute to the .init section an instruction to
648 push a word containing 0 (or some equivalent of that).
650 ASM_OUTPUT_CONSTRUCTOR should be defined
651 to push the address of the constructor. */
653 #define ASM_LONG "\tlong"
654 #undef INIT_SECTION_ASM_OP
655 #define INIT_SECTION_ASM_OP "section\t~init"
656 #undef FINI_SECTION_ASM_OP
657 #define FINI_SECTION_ASM_OP "section\t~fini"
658 #undef CONST_SECTION_ASM_OP
659 #define CONST_SECTION_ASM_OP "section\t~rodata"
661 #define CTOR_LIST_BEGIN \
662 asm (INIT_SECTION_ASM_OP); \
664 #define CTOR_LIST_END CTOR_LIST_BEGIN
666 #define BSS_SECTION_ASM_OP "section\t~bss"
668 #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
671 fprintf (FILE, "\tmov.l &"); \
672 assemble_name (FILE, NAME); \
673 fprintf (FILE, ",-(%%sp)\n"); \
676 /* We do not want leading underscores. */
678 #undef ASM_OUTPUT_LABELREF
679 #define ASM_OUTPUT_LABELREF(FILE,NAME) \
680 fprintf (FILE, "%s", NAME)