OSDN Git Service

Include function.h in most files. Remove most of the global variables
[pf3gnuchains/gcc-fork.git] / gcc / config / pdp11 / pdp11.c
1 /* Subroutines for gcc2 for pdp11.
2    Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
3    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include <stdio.h>
24 #include "rtl.h"
25 #include "regs.h"
26 #include "hard-reg-set.h"
27 #include "real.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
31 #include "function.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "recog.h"
36
37 /*
38 #define FPU_REG_P(X)    ((X)>=8 && (X)<14)
39 #define CPU_REG_P(X)    ((X)>=0 && (X)<8)
40 */
41
42 /* this is the current value returned by the macro FIRST_PARM_OFFSET 
43    defined in tm.h */
44 int current_first_parm_offset;
45
46 /* This is where the condition code register lives.  */
47 /* rtx cc0_reg_rtx; - no longer needed? */
48
49 static rtx find_addr_reg (); 
50
51 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
52
53 int
54 arith_operand (op, mode)
55      rtx op;
56      enum machine_mode mode;
57 {
58   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
59 }
60
61 int
62 const_immediate_operand (op, mode)
63      rtx op;
64      enum machine_mode mode;
65 {
66   return (GET_CODE (op) == CONST_INT);
67 }
68
69 int 
70 immediate15_operand (op, mode)
71      rtx op;
72      enum machine_mode mode;
73 {
74     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
75 }
76
77 int
78 expand_shift_operand (op, mode)
79   rtx op;
80   enum machine_mode mode;
81 {
82     return (GET_CODE (op) == CONST_INT 
83             && abs (INTVAL(op)) > 1 
84             && abs (INTVAL(op)) <= 4);
85 }
86
87 /*
88    stream is a stdio stream to output the code to.
89    size is an int: how many units of temporary storage to allocate.
90    Refer to the array `regs_ever_live' to determine which registers
91    to save; `regs_ever_live[I]' is nonzero if register number I
92    is ever used in the function.  This macro is responsible for
93    knowing which registers should not be saved even if used.  
94 */
95
96 void 
97 output_function_prologue(stream, size)
98   FILE *stream;
99   int size;
100 {                                                              
101     int fsize = ((size) + 1) & ~1;                                      
102     int regno;
103
104     int via_ac = -1;
105     
106     fprintf (stream, "\n\t;     /* function prologue %s*/\n", current_function_name);           
107
108     /* if we are outputting code for main, 
109        the switch FPU to right mode if TARGET_FPU */
110     if ( (strcmp ("main", current_function_name) == 0)
111          && TARGET_FPU)
112     {
113         fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
114         fprintf(stream, "\tsetd\n");
115         fprintf(stream, "\tseti\n\n");
116     }
117     
118     if (frame_pointer_needed)                                   
119     {                                                           
120         fprintf(stream, "\tmov fp, -(sp)\n");                   
121         fprintf(stream, "\tmov sp, fp\n");                              
122     }                                                           
123     else                                                                
124     {                                                           
125         /* DON'T SAVE FP */
126     }                                                           
127
128     /* make frame */
129     if (fsize)                                                  
130         fprintf (stream, "\tsub $%o, sp\n", fsize);                     
131
132     /* save CPU registers  */
133     for (regno = 0; regno < 8; regno++)                         
134         if (regs_ever_live[regno] && ! call_used_regs[regno])   
135             if (! ((regno == FRAME_POINTER_REGNUM)                      
136                    && frame_pointer_needed))                            
137                 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);        
138     /* fpu regs saving */
139     
140     /* via_ac specifies the ac to use for saving ac4, ac5 */
141     via_ac = -1;
142     
143     for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++) 
144     {
145         /* ac0 - ac3 */                                         
146         if (LOAD_FPU_REG_P(regno)
147             && regs_ever_live[regno] 
148             && ! call_used_regs[regno])
149         {
150             fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
151             via_ac = regno;
152         }
153         
154         /* maybe make ac4, ac5 call used regs?? */
155         /* ac4 - ac5 */
156         if (NO_LOAD_FPU_REG_P(regno)
157             && regs_ever_live[regno]
158             && ! call_used_regs[regno])
159         {
160             if (via_ac == -1)
161                 abort();
162             
163             fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
164             fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
165         }
166     }
167
168     fprintf (stream, "\t;/* end of prologue */\n\n");           
169 }
170
171 /*
172    The function epilogue should not depend on the current stack pointer!
173    It should use the frame pointer only.  This is mandatory because
174    of alloca; we also take advantage of it to omit stack adjustments
175    before returning.  */
176
177 /* maybe we can make leaf functions faster by switching to the
178    second register file - this way we don't have to save regs!
179    leaf functions are ~ 50% of all functions (dynamically!) 
180
181    set/clear bit 11 (dec. 2048) of status word for switching register files - 
182    but how can we do this? the pdp11/45 manual says bit may only 
183    be set (p.24), but not cleared!
184
185    switching to kernel is probably more expensive, so we'll leave it 
186    like this and not use the second set of registers... 
187
188    maybe as option if you want to generate code for kernel mode? */
189
190
191 void 
192 output_function_epilogue(stream, size)
193   FILE *stream;
194   int size;
195 {                                                               
196     int fsize = ((size) + 1) & ~1;                                      
197     int i, j, k;
198
199     int via_ac;
200     
201     fprintf (stream, "\n\t;     /*function epilogue */\n");             
202
203     if (frame_pointer_needed)                                   
204     {                                                           
205         /* hope this is safe - m68k does it also .... */                
206         regs_ever_live[FRAME_POINTER_REGNUM] = 0;                       
207                                                                 
208         for (i =7, j = 0 ; i >= 0 ; i--)                                
209             if (regs_ever_live[i] && ! call_used_regs[i])               
210                 j++;
211         
212         /* remember # of pushed bytes for CPU regs */
213         k = 2*j;
214         
215         for (i =7 ; i >= 0 ; i--)                                       
216             if (regs_ever_live[i] && ! call_used_regs[i])               
217                 fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[i]);
218
219         /* get ACs */                                           
220         via_ac = FIRST_PSEUDO_REGISTER -1;
221         
222         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
223             if (regs_ever_live[i] && ! call_used_regs[i])
224             {
225                 via_ac = i;
226                 k += 8;
227             }
228         
229         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
230         {
231             if (LOAD_FPU_REG_P(i)
232                 && regs_ever_live[i]
233                 && ! call_used_regs[i])
234             {
235                 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
236                 k -= 8;
237             }
238             
239             if (NO_LOAD_FPU_REG_P(i)
240                 && regs_ever_live[i]
241                 && ! call_used_regs[i])
242             {
243                 if (! LOAD_FPU_REG_P(via_ac))
244                     abort();
245                     
246                 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[via_ac]);
247                 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
248                 k -= 8;
249             }
250         }
251         
252         fprintf(stream, "\tmov fp, sp\n");                              
253         fprintf (stream, "\tmov (sp)+, fp\n");                          
254     }                                                           
255     else                                                                
256     {              
257         via_ac = FIRST_PSEUDO_REGISTER -1;
258         
259         /* get ACs */
260         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
261             if (regs_ever_live[i] && call_used_regs[i])
262                 via_ac = i;
263         
264         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
265         {
266             if (LOAD_FPU_REG_P(i)
267                 && regs_ever_live[i]
268                 && ! call_used_regs[i])
269               fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
270             
271             if (NO_LOAD_FPU_REG_P(i)
272                 && regs_ever_live[i]
273                 && ! call_used_regs[i])
274             {
275                 if (! LOAD_FPU_REG_P(via_ac))
276                     abort();
277                     
278                 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
279                 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
280             }
281         }
282
283         for (i=7; i >= 0; i--)                                  
284             if (regs_ever_live[i] && !call_used_regs[i])                
285                 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
286                                                                 
287         if (fsize)                                              
288             fprintf((stream), "\tadd $%o, sp\n", fsize);                
289     }                   
290                                         
291     fprintf (stream, "\trts pc\n");                                     
292     fprintf (stream, "\t;/* end of epilogue*/\n\n\n");          
293 }
294         
295 /* Return the best assembler insn template
296    for moving operands[1] into operands[0] as a fullword.  */
297 static char *
298 singlemove_string (operands)
299      rtx *operands;
300 {
301   if (operands[1] != const0_rtx)
302     return "mov %1,%0";
303
304   return "clr %0";
305 }
306
307 \f
308 /* Output assembler code to perform a doubleword move insn
309    with operands OPERANDS.  */
310
311 char *
312 output_move_double (operands)
313      rtx *operands;
314 {
315   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
316   rtx latehalf[2];
317   rtx addreg0 = 0, addreg1 = 0;
318
319   /* First classify both operands.  */
320
321   if (REG_P (operands[0]))
322     optype0 = REGOP;
323   else if (offsettable_memref_p (operands[0]))
324     optype0 = OFFSOP;
325   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
326     optype0 = POPOP;
327   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
328     optype0 = PUSHOP;
329   else if (GET_CODE (operands[0]) == MEM)
330     optype0 = MEMOP;
331   else
332     optype0 = RNDOP;
333
334   if (REG_P (operands[1]))
335     optype1 = REGOP;
336   else if (CONSTANT_P (operands[1]))
337 #if 0
338            || GET_CODE (operands[1]) == CONST_DOUBLE)
339 #endif
340     optype1 = CNSTOP;
341   else if (offsettable_memref_p (operands[1]))
342     optype1 = OFFSOP;
343   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
344     optype1 = POPOP;
345   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
346     optype1 = PUSHOP;
347   else if (GET_CODE (operands[1]) == MEM)
348     optype1 = MEMOP;
349   else
350     optype1 = RNDOP;
351
352   /* Check for the cases that the operand constraints are not
353      supposed to allow to happen.  Abort if we get one,
354      because generating code for these cases is painful.  */
355
356   if (optype0 == RNDOP || optype1 == RNDOP)
357     abort ();
358
359   /* If one operand is decrementing and one is incrementing
360      decrement the former register explicitly
361      and change that operand into ordinary indexing.  */
362
363   if (optype0 == PUSHOP && optype1 == POPOP)
364     {
365       operands[0] = XEXP (XEXP (operands[0], 0), 0);
366       output_asm_insn ("sub $4,%0", operands);
367       operands[0] = gen_rtx (MEM, SImode, operands[0]);
368       optype0 = OFFSOP;
369     }
370   if (optype0 == POPOP && optype1 == PUSHOP)
371     {
372       operands[1] = XEXP (XEXP (operands[1], 0), 0);
373       output_asm_insn ("sub $4,%1", operands);
374       operands[1] = gen_rtx (MEM, SImode, operands[1]);
375       optype1 = OFFSOP;
376     }
377
378   /* If an operand is an unoffsettable memory ref, find a register
379      we can increment temporarily to make it refer to the second word.  */
380
381   if (optype0 == MEMOP)
382     addreg0 = find_addr_reg (XEXP (operands[0], 0));
383
384   if (optype1 == MEMOP)
385     addreg1 = find_addr_reg (XEXP (operands[1], 0));
386
387   /* Ok, we can do one word at a time.
388      Normally we do the low-numbered word first,
389      but if either operand is autodecrementing then we
390      do the high-numbered word first.
391
392      In either case, set up in LATEHALF the operands to use
393      for the high-numbered word and in some cases alter the
394      operands in OPERANDS to be suitable for the low-numbered word.  */
395
396   if (optype0 == REGOP)
397     latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
398   else if (optype0 == OFFSOP)
399     latehalf[0] = adj_offsettable_operand (operands[0], 2);
400   else
401     latehalf[0] = operands[0];
402
403   if (optype1 == REGOP)
404     latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
405   else if (optype1 == OFFSOP)
406     latehalf[1] = adj_offsettable_operand (operands[1], 2);
407   else if (optype1 == CNSTOP)
408     {
409         if (CONSTANT_P (operands[1]))
410         {
411             /* now the mess begins, high word is in lower word??? 
412
413                that's what ashc makes me think, but I don't remember :-( */
414             latehalf[1] = GEN_INT (INTVAL(operands[1])>>16);
415             operands[1] = GEN_INT (INTVAL(operands[1])&0xff);
416         }
417       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
418         {
419             /* immediate 32 bit values not allowed */
420             abort();
421         }
422     }
423   else
424     latehalf[1] = operands[1];
425
426   /* If insn is effectively movd N(sp),-(sp) then we will do the
427      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
428      for the low word as well, to compensate for the first decrement of sp.  */
429   if (optype0 == PUSHOP
430       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
431       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
432     operands[1] = latehalf[1];
433
434   /* If one or both operands autodecrementing,
435      do the two words, high-numbered first.  */
436
437   /* Likewise,  the first move would clobber the source of the second one,
438      do them in the other order.  This happens only for registers;
439      such overlap can't happen in memory unless the user explicitly
440      sets it up, and that is an undefined circumstance.  */
441
442   if (optype0 == PUSHOP || optype1 == PUSHOP
443       || (optype0 == REGOP && optype1 == REGOP
444           && REGNO (operands[0]) == REGNO (latehalf[1])))
445     {
446       /* Make any unoffsettable addresses point at high-numbered word.  */
447       if (addreg0)
448         output_asm_insn ("add $2,%0", &addreg0);
449       if (addreg1)
450         output_asm_insn ("add $2,%0", &addreg1);
451
452       /* Do that word.  */
453       output_asm_insn (singlemove_string (latehalf), latehalf);
454
455       /* Undo the adds we just did.  */
456       if (addreg0)
457         output_asm_insn ("sub $2,%0", &addreg0);
458       if (addreg1)
459         output_asm_insn ("sub $2,%0", &addreg1);
460
461       /* Do low-numbered word.  */
462       return singlemove_string (operands);
463     }
464
465   /* Normal case: do the two words, low-numbered first.  */
466
467   output_asm_insn (singlemove_string (operands), operands);
468
469   /* Make any unoffsettable addresses point at high-numbered word.  */
470   if (addreg0)
471     output_asm_insn ("add $2,%0", &addreg0);
472   if (addreg1)
473     output_asm_insn ("add $2,%0", &addreg1);
474
475   /* Do that word.  */
476   output_asm_insn (singlemove_string (latehalf), latehalf);
477
478   /* Undo the adds we just did.  */
479   if (addreg0)
480     output_asm_insn ("sub $2,%0", &addreg0);
481   if (addreg1)
482     output_asm_insn ("sub $2,%0", &addreg1);
483
484   return "";
485 }
486 /* Output assembler code to perform a quadword move insn
487    with operands OPERANDS.  */
488
489 char *
490 output_move_quad (operands)
491      rtx *operands;
492 {
493   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
494   rtx latehalf[2];
495   rtx addreg0 = 0, addreg1 = 0;
496
497   output_asm_insn(";; movdi/df: %1 -> %0", operands);
498   
499   if (REG_P (operands[0]))
500     optype0 = REGOP;
501   else if (offsettable_memref_p (operands[0]))
502     optype0 = OFFSOP;
503   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
504     optype0 = POPOP;
505   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
506     optype0 = PUSHOP;
507   else if (GET_CODE (operands[0]) == MEM)
508     optype0 = MEMOP;
509   else
510     optype0 = RNDOP;
511
512   if (REG_P (operands[1]))
513     optype1 = REGOP;
514   else if (CONSTANT_P (operands[1])
515            || GET_CODE (operands[1]) == CONST_DOUBLE)
516     optype1 = CNSTOP;
517   else if (offsettable_memref_p (operands[1]))
518     optype1 = OFFSOP;
519   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
520     optype1 = POPOP;
521   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
522     optype1 = PUSHOP;
523   else if (GET_CODE (operands[1]) == MEM)
524     optype1 = MEMOP;
525   else
526     optype1 = RNDOP;
527
528   /* Check for the cases that the operand constraints are not
529      supposed to allow to happen.  Abort if we get one,
530      because generating code for these cases is painful.  */
531
532   if (optype0 == RNDOP || optype1 == RNDOP)
533     abort ();
534   
535   /* check if we move a CPU reg to an FPU reg, or vice versa! */
536   if (optype0 == REGOP && optype1 == REGOP)
537       /* bogus - 64 bit cannot reside in CPU! */
538       if (CPU_REG_P(REGNO(operands[0]))
539           || CPU_REG_P (REGNO(operands[1])))
540           abort();
541   
542   if (optype0 == REGOP || optype1 == REGOP)
543   {
544       /* check for use of clrd???? 
545          if you ever allow ac4 and ac5 (now we require secondary load) 
546          you must check whether 
547          you want to load into them or store from them - 
548          then dump ac0 into $help$ movce ac4/5 to ac0, do the 
549          store from ac0, and restore ac0 - if you can find 
550          an unused ac[0-3], use that and you save a store and a load!*/
551
552       if (FPU_REG_P(REGNO(operands[0])))
553       {
554           if (GET_CODE(operands[1]) == CONST_DOUBLE)
555           {
556               union { double d; int i[2]; } u;
557               u.i[0] = CONST_DOUBLE_LOW (operands[1]); 
558               u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
559               
560               if (u.d == 0.0)
561                   return "{clrd|clrf} %0";
562           }
563               
564           return "{ldd|movf} %1, %0";
565       }
566       
567       if (FPU_REG_P(REGNO(operands[1])))
568           return "{std|movf} %1, %0";
569   }
570       
571   /* If one operand is decrementing and one is incrementing
572      decrement the former register explicitly
573      and change that operand into ordinary indexing.  */
574
575   if (optype0 == PUSHOP && optype1 == POPOP)
576     {
577       operands[0] = XEXP (XEXP (operands[0], 0), 0);
578       output_asm_insn ("sub $8,%0", operands);
579       operands[0] = gen_rtx (MEM, DImode, operands[0]);
580       optype0 = OFFSOP;
581     }
582   if (optype0 == POPOP && optype1 == PUSHOP)
583     {
584       operands[1] = XEXP (XEXP (operands[1], 0), 0);
585       output_asm_insn ("sub $8,%1", operands);
586       operands[1] = gen_rtx (MEM, SImode, operands[1]);
587       optype1 = OFFSOP;
588     }
589
590   /* If an operand is an unoffsettable memory ref, find a register
591      we can increment temporarily to make it refer to the second word.  */
592
593   if (optype0 == MEMOP)
594     addreg0 = find_addr_reg (XEXP (operands[0], 0));
595
596   if (optype1 == MEMOP)
597     addreg1 = find_addr_reg (XEXP (operands[1], 0));
598
599   /* Ok, we can do one word at a time.
600      Normally we do the low-numbered word first,
601      but if either operand is autodecrementing then we
602      do the high-numbered word first.
603
604      In either case, set up in LATEHALF the operands to use
605      for the high-numbered word and in some cases alter the
606      operands in OPERANDS to be suitable for the low-numbered word.  */
607
608   if (optype0 == REGOP)
609     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
610   else if (optype0 == OFFSOP)
611     latehalf[0] = adj_offsettable_operand (operands[0], 4);
612   else
613     latehalf[0] = operands[0];
614
615   if (optype1 == REGOP)
616     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
617   else if (optype1 == OFFSOP)
618     latehalf[1] = adj_offsettable_operand (operands[1], 4);
619   else if (optype1 == CNSTOP)
620     {
621       if (GET_CODE (operands[1]) == CONST_DOUBLE)
622         {
623             /* floats only. not yet supported!
624
625              -- compute it into PDP float format, - internally,
626              just use IEEE and ignore possible problems ;-)
627
628              we might get away with it !!!! */
629
630             abort();
631             
632 #ifndef HOST_WORDS_BIG_ENDIAN
633           latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
634           operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
635 #else /* HOST_WORDS_BIG_ENDIAN */
636           latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
637           operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
638 #endif /* HOST_WORDS_BIG_ENDIAN */
639         }
640       else if (GET_CODE(operands[1]) == CONST_INT)
641       {
642           latehalf[1] = GEN_INT (0);
643       }
644       else
645           abort();
646       
647     }
648   else
649     latehalf[1] = operands[1];
650
651   /* If insn is effectively movd N(sp),-(sp) then we will do the
652      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
653      for the low word as well, to compensate for the first decrement of sp.  */
654   if (optype0 == PUSHOP
655       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
656       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
657     operands[1] = latehalf[1];
658
659   /* If one or both operands autodecrementing,
660      do the two words, high-numbered first.  */
661
662   /* Likewise,  the first move would clobber the source of the second one,
663      do them in the other order.  This happens only for registers;
664      such overlap can't happen in memory unless the user explicitly
665      sets it up, and that is an undefined circumstance.  */
666
667   if (optype0 == PUSHOP || optype1 == PUSHOP
668       || (optype0 == REGOP && optype1 == REGOP
669           && REGNO (operands[0]) == REGNO (latehalf[1])))
670     {
671       /* Make any unoffsettable addresses point at high-numbered word.  */
672       if (addreg0)
673         output_asm_insn ("add $4,%0", &addreg0);
674       if (addreg1)
675         output_asm_insn ("add $4,%0", &addreg1);
676
677       /* Do that word.  */
678       output_asm_insn(output_move_double(latehalf), latehalf);
679
680       /* Undo the adds we just did.  */
681       if (addreg0)
682         output_asm_insn ("sub $4,%0", &addreg0);
683       if (addreg1)
684         output_asm_insn ("sub $4,%0", &addreg1);
685
686       /* Do low-numbered word.  */
687       return output_move_double (operands);
688     }
689
690   /* Normal case: do the two words, low-numbered first.  */
691
692   output_asm_insn (output_move_double (operands), operands);
693
694   /* Make any unoffsettable addresses point at high-numbered word.  */
695   if (addreg0)
696     output_asm_insn ("add $4,%0", &addreg0);
697   if (addreg1)
698     output_asm_insn ("add $4,%0", &addreg1);
699
700   /* Do that word.  */
701   output_asm_insn (output_move_double (latehalf), latehalf);
702
703   /* Undo the adds we just did.  */
704   if (addreg0)
705     output_asm_insn ("sub $4,%0", &addreg0);
706   if (addreg1)
707     output_asm_insn ("sub $4,%0", &addreg1);
708
709   return "";
710 }
711
712 \f
713 /* Return a REG that occurs in ADDR with coefficient 1.
714    ADDR can be effectively incremented by incrementing REG.  */
715
716 static rtx
717 find_addr_reg (addr)
718      rtx addr;
719 {
720   while (GET_CODE (addr) == PLUS)
721     {
722       if (GET_CODE (XEXP (addr, 0)) == REG)
723         addr = XEXP (addr, 0);
724       if (GET_CODE (XEXP (addr, 1)) == REG)
725         addr = XEXP (addr, 1);
726       if (CONSTANT_P (XEXP (addr, 0)))
727         addr = XEXP (addr, 1);
728       if (CONSTANT_P (XEXP (addr, 1)))
729         addr = XEXP (addr, 0);
730     }
731   if (GET_CODE (addr) == REG)
732     return addr;
733   return 0;
734 }
735 \f
736 /* Output an ascii string.  */
737 void
738 output_ascii (file, p, size)
739      FILE *file;
740      char *p;
741      int size;
742 {
743   int i;
744
745   /* This used to output .byte "string", which doesn't work with the UNIX
746      assembler and I think not with DEC ones either.  */
747   fprintf (file, "\t.byte ");
748
749   for (i = 0; i < size; i++)
750     {
751       register int c = p[i];
752       if (c < 0)
753         c += 256;
754       fprintf (file, "%o", c);
755       if (i < size - 1)
756         putc (',', file);
757     }
758   putc ('\n', file);
759 }
760
761
762 /* --- stole from out-vax, needs changes */
763
764 void
765 print_operand_address (file, addr)
766      FILE *file;
767      register rtx addr;
768 {
769   register rtx reg1, reg2, breg, ireg;
770   rtx offset;
771
772  retry:
773
774   switch (GET_CODE (addr))
775     {
776     case MEM:
777       if (TARGET_UNIX_ASM)
778         fprintf (file, "*");
779       else
780         fprintf (file, "@");
781       addr = XEXP (addr, 0);
782       goto retry;
783
784     case REG:
785       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
786       break;
787
788     case PRE_DEC:
789       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
790       break;
791
792     case POST_INC:
793       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
794       break;
795
796     case PLUS:
797       reg1 = 0; reg2 = 0;
798       ireg = 0; breg = 0;
799       offset = 0;
800       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
801           || GET_CODE (XEXP (addr, 0)) == MEM)
802         {
803           offset = XEXP (addr, 0);
804           addr = XEXP (addr, 1);
805         }
806       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
807                || GET_CODE (XEXP (addr, 1)) == MEM)
808         {
809           offset = XEXP (addr, 1);
810           addr = XEXP (addr, 0);
811         }
812       if (GET_CODE (addr) != PLUS)
813         ;
814       else if (GET_CODE (XEXP (addr, 0)) == MULT)
815         {
816           reg1 = XEXP (addr, 0);
817           addr = XEXP (addr, 1);
818         }
819       else if (GET_CODE (XEXP (addr, 1)) == MULT)
820         {
821           reg1 = XEXP (addr, 1);
822           addr = XEXP (addr, 0);
823         }
824       else if (GET_CODE (XEXP (addr, 0)) == REG)
825         {
826           reg1 = XEXP (addr, 0);
827           addr = XEXP (addr, 1);
828         }
829       else if (GET_CODE (XEXP (addr, 1)) == REG)
830         {
831           reg1 = XEXP (addr, 1);
832           addr = XEXP (addr, 0);
833         }
834       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
835         {
836           if (reg1 == 0)
837             reg1 = addr;
838           else
839             reg2 = addr;
840           addr = 0;
841         }
842       if (offset != 0)
843         {
844           if (addr != 0) abort ();
845           addr = offset;
846         }
847       if (reg1 != 0 && GET_CODE (reg1) == MULT)
848         {
849           breg = reg2;
850           ireg = reg1;
851         }
852       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
853         {
854           breg = reg1;
855           ireg = reg2;
856         }
857       else if (reg2 != 0 || GET_CODE (addr) == MEM)
858         {
859           breg = reg2;
860           ireg = reg1;
861         }
862       else
863         {
864           breg = reg1;
865           ireg = reg2;
866         }
867       if (addr != 0)
868         output_address (addr);
869       if (breg != 0)
870         {
871           if (GET_CODE (breg) != REG)
872             abort ();
873           fprintf (file, "(%s)", reg_names[REGNO (breg)]);
874         }
875       if (ireg != 0)
876         {
877           if (GET_CODE (ireg) == MULT)
878             ireg = XEXP (ireg, 0);
879           if (GET_CODE (ireg) != REG)
880             abort ();
881           abort();
882           fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
883         }
884       break;
885
886     default:
887       output_addr_const_pdp11 (file, addr);
888     }
889 }
890
891 /* register move costs, indexed by regs */
892
893 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
894 {
895              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
896
897 /* NO */     {  0,   0,   0,    0,    0,    0,   0},
898 /* MUL */    {  0,   2,   2,   10,   22,   22,  22},
899 /* GEN */    {  0,   2,   2,   10,   22,   22,  22},
900 /* LFPU */   {  0,  10,  10,    2,    2,    2,  10},
901 /* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},
902 /* FPU */    {  0,  22,  22,    2,    2,    2,  22},
903 /* ALL */    {  0,  22,  22,   10,   22,   22,  22}
904 }  ;
905
906
907 /* -- note that some moves are tremendously expensive, 
908    because they require lots of tricks! do we have to 
909    charge the costs incurred by secondary reload class 
910    -- as we do here with 22 -- or not ? */
911
912 int 
913 register_move_cost(c1, c2)
914   enum reg_class c1, c2;
915 {
916     return move_costs[(int)c1][(int)c2];
917 }
918
919 char *
920 output_jump(pos, neg, length)
921   int length;
922   char *pos, *neg;
923 {
924     static int x = 0;
925     
926     static char buf[1000];
927
928 #if 0
929 /* currently we don't need this, because the tstdf and cmpdf 
930    copy the condition code immediately, and other float operations are not 
931    yet recognized as changing the FCC - if so, then the length-cost of all
932    jump insns increases by one, because we have to potentially copy the 
933    FCC! */
934     if (cc_status.flags & CC_IN_FPU)
935         output_asm_insn("cfcc", NULL);
936 #endif
937         
938     switch (length)
939     {
940       case 1:
941         
942         strcpy(buf, pos);
943         strcat(buf, " %l0");
944         
945         return buf;
946         
947       case 3:
948         
949         sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
950         
951         x++;
952         
953         return buf;
954         
955       default:
956         
957         abort();
958     }
959     
960 }
961
962 void
963 notice_update_cc_on_set(exp, insn)
964   rtx exp;
965   rtx insn;
966 {
967     if (GET_CODE (SET_DEST (exp)) == CC0)
968     { 
969         cc_status.flags = 0;                                    
970         cc_status.value1 = SET_DEST (exp);                      
971         cc_status.value2 = SET_SRC (exp);                       
972
973 /*
974         if (GET_MODE(SET_SRC(exp)) == DFmode)
975             cc_status.flags |= CC_IN_FPU;
976 */      
977     }                                                   
978     else if ((GET_CODE (SET_DEST (exp)) == REG          
979               || GET_CODE (SET_DEST (exp)) == MEM)              
980              && GET_CODE (SET_SRC (exp)) != PC          
981              && (GET_MODE (SET_DEST(exp)) == HImode             
982                  || GET_MODE (SET_DEST(exp)) == QImode) 
983                 && (GET_CODE (SET_SRC(exp)) == PLUS             
984                     || GET_CODE (SET_SRC(exp)) == MINUS 
985                     || GET_CODE (SET_SRC(exp)) == AND   
986                     || GET_CODE (SET_SRC(exp)) == IOR   
987                     || GET_CODE (SET_SRC(exp)) == XOR   
988                     || GET_CODE (SET_SRC(exp)) == NOT   
989                     || GET_CODE (SET_SRC(exp)) == NEG   
990                         || GET_CODE (SET_SRC(exp)) == REG       
991                     || GET_CODE (SET_SRC(exp)) == MEM)) 
992     { 
993         cc_status.flags = 0;                                    
994         cc_status.value1 = SET_SRC (exp);                       
995         cc_status.value2 = SET_DEST (exp);                      
996         
997         if (cc_status.value1 && GET_CODE (cc_status.value1) == REG      
998             && cc_status.value2                                 
999             && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1000             cc_status.value2 = 0;                                       
1001         if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM      
1002             && cc_status.value2                                 
1003             && GET_CODE (cc_status.value2) == MEM)                      
1004             cc_status.value2 = 0;                                       
1005     }                                                   
1006     else if (GET_CODE (SET_SRC (exp)) == CALL)          
1007     { 
1008         CC_STATUS_INIT; 
1009     }
1010     else if (GET_CODE (SET_DEST (exp)) == REG)                  
1011         /* what's this ? */                                     
1012     { 
1013         if ((cc_status.value1                                   
1014              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1015             cc_status.value1 = 0;                               
1016         if ((cc_status.value2                                   
1017              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1018             cc_status.value2 = 0;                               
1019     }                                                   
1020     else if (SET_DEST(exp) == pc_rtx)
1021     { 
1022         /* jump */
1023     }
1024     else /* if (GET_CODE (SET_DEST (exp)) == MEM)       */      
1025     {  
1026         /* the last else is a bit paranoiac, but since nearly all instructions 
1027            play with condition codes, it's reasonable! */
1028
1029         CC_STATUS_INIT; /* paranoia*/ 
1030     }                   
1031 }
1032
1033
1034 int simple_memory_operand(op, mode)
1035   rtx op;
1036   enum machine_mode mode;
1037 {
1038     rtx addr;
1039
1040     /* Eliminate non-memory operations */
1041     if (GET_CODE (op) != MEM)
1042         return FALSE;
1043
1044 #if 0
1045     /* dword operations really put out 2 instructions, so eliminate them.  */
1046     if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1047         return FALSE;
1048 #endif
1049
1050     /* Decode the address now.  */
1051
1052   indirection:
1053     
1054     addr = XEXP (op, 0);
1055
1056     switch (GET_CODE (addr))
1057     {
1058       case REG:
1059         /* (R0) - no extra cost */
1060         return 1;
1061         
1062       case PRE_DEC:
1063       case POST_INC:
1064         /* -(R0), (R0)+ - cheap! */
1065         return 0;
1066         
1067       case MEM:
1068         /* cheap - is encoded in addressing mode info! 
1069
1070            -- except for @(R0), which has to be @0(R0) !!! */
1071
1072         if (GET_CODE (XEXP (addr, 0)) == REG)
1073             return 0;
1074         
1075         op=addr;
1076         goto indirection;
1077         
1078       case CONST_INT:
1079       case LABEL_REF:          
1080       case CONST:
1081       case SYMBOL_REF:
1082         /* @#address - extra cost */
1083         return 0;
1084
1085       case PLUS:
1086         /* X(R0) - extra cost */
1087         return 0;
1088
1089       default:
1090         break;
1091     }
1092     
1093     return FALSE;
1094 }
1095
1096
1097 /*
1098  * output a block move:
1099  *
1100  * operands[0]  ... to
1101  * operands[1]  ... from
1102  * operands[2]  ... length
1103  * operands[3]  ... alignment
1104  * operands[4]  ... scratch register
1105  */
1106
1107  
1108 char *
1109 output_block_move(operands)
1110   rtx *operands;
1111 {
1112     static int count = 0;
1113     char buf[200];
1114     
1115     if (GET_CODE(operands[2]) == CONST_INT
1116         && ! optimize_size)
1117     {
1118         if (INTVAL(operands[2]) < 16
1119             && INTVAL(operands[3]) == 1)
1120         {
1121             register int i;
1122             
1123             for (i = 1; i <= INTVAL(operands[2]); i++)
1124                 output_asm_insn("movb (%1)+, (%0)+", operands);
1125
1126             return "";
1127         }
1128         else if (INTVAL(operands[2]) < 32)
1129         {
1130             register int i;
1131             
1132             for (i = 1; i <= INTVAL(operands[2])/2; i++)
1133                 output_asm_insn("mov (%1)+, (%0)+", operands);
1134             
1135             /* may I assume that moved quantity is 
1136                multiple of alignment ???
1137
1138                I HOPE SO !
1139             */
1140
1141             return "";
1142         }
1143         
1144
1145         /* can do other clever things, maybe... */
1146     }
1147
1148     if (CONSTANT_P(operands[2]) )
1149     {
1150         /* just move count to scratch */
1151         output_asm_insn("mov %2, %4", operands);
1152     }
1153     else
1154     {
1155         /* just clobber the register */
1156         operands[4] = operands[2];
1157     }
1158     
1159
1160     /* switch over alignment */
1161     switch (INTVAL(operands[3]))
1162     {
1163       case 1:
1164         
1165         /* 
1166           x:
1167           movb (%1)+, (%0)+
1168           
1169           if (TARGET_45)
1170              sob %4,x
1171           else
1172              dec %4
1173              bgt x
1174
1175         */
1176
1177         sprintf(buf, "\nmovestrhi%d:", count);
1178         output_asm_insn(buf, NULL);
1179         
1180         output_asm_insn("movb (%1)+, (%0)+", operands);
1181         
1182         if (TARGET_45)
1183         {
1184             sprintf(buf, "sob %%4, movestrhi%d", count);
1185             output_asm_insn(buf, operands);
1186         }
1187         else
1188         {
1189             output_asm_insn("dec %4", operands);
1190             
1191             sprintf(buf, "bgt movestrhi%d", count);
1192             output_asm_insn(buf, NULL);
1193         }
1194         
1195         count ++;
1196         break;
1197         
1198       case 2:
1199         
1200         /* 
1201            asr %4
1202
1203            x:
1204
1205            mov (%1)+, (%0)+
1206
1207            if (TARGET_45)
1208              sob %4, x
1209            else
1210              dec %4
1211              bgt x
1212         */
1213
1214       generate_compact_code:
1215
1216         output_asm_insn("asr %4", operands);
1217
1218         sprintf(buf, "\nmovestrhi%d:", count);
1219         output_asm_insn(buf, NULL);
1220         
1221         output_asm_insn("mov (%1)+, (%0)+", operands);
1222         
1223         if (TARGET_45)
1224         {
1225             sprintf(buf, "sob %%4, movestrhi%d", count);
1226             output_asm_insn(buf, operands);
1227         }
1228         else
1229         {
1230             output_asm_insn("dec %4", operands);
1231             
1232             sprintf(buf, "bgt movestrhi%d", count);
1233             output_asm_insn(buf, NULL);
1234         }
1235         
1236         count ++;
1237         break;
1238
1239       case 4:
1240         
1241         /*
1242
1243            asr %4
1244            asr %4
1245
1246            x:
1247
1248            mov (%1)+, (%0)+
1249            mov (%1)+, (%0)+
1250
1251            if (TARGET_45)
1252              sob %4, x
1253            else
1254              dec %4
1255              bgt x
1256         */
1257
1258         if (optimize_size)
1259             goto generate_compact_code;
1260         
1261         output_asm_insn("asr %4", operands);
1262         output_asm_insn("asr %4", operands);
1263
1264         sprintf(buf, "\nmovestrhi%d:", count);
1265         output_asm_insn(buf, NULL);
1266         
1267         output_asm_insn("mov (%1)+, (%0)+", operands);
1268         output_asm_insn("mov (%1)+, (%0)+", operands);
1269         
1270         if (TARGET_45)
1271         {
1272             sprintf(buf, "sob %%4, movestrhi%d", count);
1273             output_asm_insn(buf, operands);
1274         }
1275         else
1276         {
1277             output_asm_insn("dec %4", operands);
1278             
1279             sprintf(buf, "bgt movestrhi%d", count);
1280             output_asm_insn(buf, NULL);
1281         }
1282         
1283         count ++;
1284         break;
1285        
1286       default:
1287         
1288         /*
1289            
1290            asr %4
1291            asr %4
1292            asr %4
1293
1294            x:
1295
1296            mov (%1)+, (%0)+
1297            mov (%1)+, (%0)+
1298            mov (%1)+, (%0)+
1299            mov (%1)+, (%0)+
1300            
1301            if (TARGET_45)
1302              sob %4, x
1303            else
1304              dec %4
1305              bgt x
1306         */
1307
1308
1309         if (optimize_size)
1310             goto generate_compact_code;
1311         
1312         output_asm_insn("asr %4", operands);
1313         output_asm_insn("asr %4", operands);
1314         output_asm_insn("asr %4", operands);
1315
1316         sprintf(buf, "\nmovestrhi%d:", count);
1317         output_asm_insn(buf, NULL);
1318         
1319         output_asm_insn("mov (%1)+, (%0)+", operands);
1320         output_asm_insn("mov (%1)+, (%0)+", operands);
1321         output_asm_insn("mov (%1)+, (%0)+", operands);
1322         output_asm_insn("mov (%1)+, (%0)+", operands);
1323         
1324         if (TARGET_45)
1325         {
1326             sprintf(buf, "sob %%4, movestrhi%d", count);
1327             output_asm_insn(buf, operands);
1328         }
1329         else
1330         {
1331             output_asm_insn("dec %4", operands);
1332             
1333             sprintf(buf, "bgt movestrhi%d", count);
1334             output_asm_insn(buf, NULL);
1335         }
1336         
1337         count ++;
1338         break;
1339         
1340         ;
1341         
1342     }
1343     
1344     return "";
1345 }
1346
1347 /* for future use */
1348 int
1349 comparison_operator_index(op)
1350   rtx op;
1351 {
1352     switch (GET_CODE(op))
1353     {
1354       case NE:
1355         return 0;
1356         
1357       case EQ:
1358         return 1;
1359         
1360       case GE:
1361         return 2;
1362         
1363       case GT:
1364         return 3;
1365         
1366       case LE:
1367         return 4;
1368         
1369       case LT:
1370         return 5;
1371         
1372       case GEU:
1373         return 6;
1374         
1375       case GTU:
1376         return 7;
1377
1378       case LEU:
1379         return 8;
1380         
1381       case LTU:
1382         return 9;
1383         
1384       default:
1385         return -1;
1386     }
1387 }    
1388         
1389 /* tests whether the rtx is a comparison operator */
1390 int
1391 comp_operator (op, mode)
1392   rtx op;
1393   enum machine_mode mode;
1394 {
1395     return comparison_operator_index(op) >= 0;
1396 }
1397
1398     
1399 int
1400 legitimate_address_p (mode, address)
1401   enum machine_mode mode;
1402   rtx address;
1403 {
1404 /* #define REG_OK_STRICT */
1405     GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1406     
1407     return 0;
1408     
1409   win:
1410     return 1;
1411
1412 /* #undef REG_OK_STRICT */
1413 }
1414
1415 /* A copy of output_addr_const modified for pdp11 expression syntax.
1416    output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1417    use, and for debugging output, which we don't support with this port either.
1418    So this copy should get called whenever needed.
1419 */
1420 void
1421 output_addr_const_pdp11 (file, x)
1422      FILE *file;
1423      rtx x;
1424 {
1425   char buf[256];
1426
1427  restart:
1428   switch (GET_CODE (x))
1429     {
1430     case PC:
1431       if (flag_pic)
1432         putc ('.', file);
1433       else
1434         abort ();
1435       break;
1436
1437     case SYMBOL_REF:
1438       assemble_name (file, XSTR (x, 0));
1439       break;
1440
1441     case LABEL_REF:
1442       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1443       assemble_name (file, buf);
1444       break;
1445
1446     case CODE_LABEL:
1447       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1448       assemble_name (file, buf);
1449       break;
1450
1451     case CONST_INT:
1452       /* Should we check for constants which are too big?  Maybe cutting
1453          them off to 16 bits is OK?  */
1454       fprintf (file, "%ho", (unsigned short) INTVAL (x));
1455       break;
1456
1457     case CONST:
1458       /* This used to output parentheses around the expression,
1459          but that does not work on the 386 (either ATT or BSD assembler).  */
1460       output_addr_const_pdp11 (file, XEXP (x, 0));
1461       break;
1462
1463     case CONST_DOUBLE:
1464       if (GET_MODE (x) == VOIDmode)
1465         {
1466           /* We can use %o if the number is one word and positive.  */
1467           if (CONST_DOUBLE_HIGH (x))
1468             abort (); /* Should we just silently drop the high part?  */
1469           else
1470             fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
1471         }
1472       else
1473         /* We can't handle floating point constants;
1474            PRINT_OPERAND must handle them.  */
1475         output_operand_lossage ("floating constant misused");
1476       break;
1477
1478     case PLUS:
1479       /* Some assemblers need integer constants to appear last (eg masm).  */
1480       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1481         {
1482           output_addr_const_pdp11 (file, XEXP (x, 1));
1483           if (INTVAL (XEXP (x, 0)) >= 0)
1484             fprintf (file, "+");
1485           output_addr_const_pdp11 (file, XEXP (x, 0));
1486         }
1487       else
1488         {
1489           output_addr_const_pdp11 (file, XEXP (x, 0));
1490           if (INTVAL (XEXP (x, 1)) >= 0)
1491             fprintf (file, "+");
1492           output_addr_const_pdp11 (file, XEXP (x, 1));
1493         }
1494       break;
1495
1496     case MINUS:
1497       /* Avoid outputting things like x-x or x+5-x,
1498          since some assemblers can't handle that.  */
1499       x = simplify_subtraction (x);
1500       if (GET_CODE (x) != MINUS)
1501         goto restart;
1502
1503       output_addr_const_pdp11 (file, XEXP (x, 0));
1504       fprintf (file, "-");
1505       if (GET_CODE (XEXP (x, 1)) == CONST_INT
1506           && INTVAL (XEXP (x, 1)) < 0)
1507         {
1508           fprintf (file, ASM_OPEN_PAREN);
1509           output_addr_const_pdp11 (file, XEXP (x, 1));
1510           fprintf (file, ASM_CLOSE_PAREN);
1511         }
1512       else
1513         output_addr_const_pdp11 (file, XEXP (x, 1));
1514       break;
1515
1516     case ZERO_EXTEND:
1517     case SIGN_EXTEND:
1518       output_addr_const_pdp11 (file, XEXP (x, 0));
1519       break;
1520
1521     default:
1522       output_operand_lossage ("invalid expression as operand");
1523     }
1524 }