8100d90eca985c25eea5bc44e5283ee4670bbf2d
[people/dverkamp/gcc.git] / gcc / config / i86 / i86.c
1 #include <stdio.h>
2
3 #include "config.h"
4 #include "system.h"
5 #include "coretypes.h"
6 #include "tm.h"
7 #include "rtl.h"
8 #include "tree.h"
9 #include "tm_p.h"
10 #include "regs.h"
11 #include "hard-reg-set.h"
12 #include "real.h"
13 #include "insn-config.h"
14 #include "conditions.h"
15 #include "output.h"
16 #include "insn-codes.h"
17 #include "insn-attr.h"
18 #include "flags.h"
19 #include "except.h"
20 #include "function.h"
21 #include "recog.h"
22 #include "expr.h"
23 #include "optabs.h"
24 #include "toplev.h"
25 #include "basic-block.h"
26 #include "ggc.h"
27 #include "target.h"
28 #include "target-def.h"
29 #include "langhooks.h"
30 #include "cgraph.h"
31 #include "tree-gimple.h"
32 #include "dwarf2.h"
33 #include "df.h"
34 #include "tm-constrs.h"
35 #include "params.h"
36
37 static void i86_file_start (void);
38 static rtx  i86_function_value (tree, tree, bool);
39 static bool i86_rtx_costs (rtx x, int code, int outer_code_i, int *total);
40
41 const enum reg_class regclass_map[] = { AREG, AREG,  DREG, DREG,  CREG, CREG,
42                                         BREG, BREG,  SIREG, SIREG,  DIREG, DIREG,
43                                         BPREG, BPREG,  GENERAL_REGS, GENERAL_REGS };
44
45 static const char *register_names[] = REGISTER_NAMES;
46
47
48 /* Table of valid machine attributes.  */
49 static const struct attribute_spec i86_attribute_table[] =
50 {
51 #ifdef SUBTARGET_ATTRIBUTE_TABLE
52   SUBTARGET_ATTRIBUTE_TABLE,
53 #endif
54   { NULL,        0, 0, false, false, false, NULL }
55 };
56
57 /* Initialize the GCC target structure.  */
58 #undef TARGET_ATTRIBUTE_TABLE
59 #define TARGET_ATTRIBUTE_TABLE i86_attribute_table
60
61 #undef TARGET_ASM_OPEN_PAREN
62 #define TARGET_ASM_OPEN_PAREN "("
63 #undef TARGET_ASM_CLOSE_PAREN
64 #define TARGET_ASM_CLOSE_PAREN ")"
65
66 #undef TARGET_ASM_ALIGNED_HI_OP
67 #define TARGET_ASM_ALIGNED_HI_OP ASM_SHORT
68
69 #undef TARGET_ASM_UNALIGNED_HI_OP
70 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
71
72 #undef TARGET_ASM_FILE_START
73 #define TARGET_ASM_FILE_START i86_file_start
74
75 #undef TARGET_PROMOTE_PROTOTYPES
76 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
77
78 #undef TARGET_FUNCTION_VALUE
79 #define TARGET_FUNCTION_VALUE i86_function_value
80
81 #undef TARGET_RTX_COSTS
82 #define TARGET_RTX_COSTS i86_rtx_costs
83
84 struct gcc_target targetm = TARGET_INITIALIZER;
85
86
87 int
88 i86_reg_class_from_letter(int c)
89 {
90   switch (c)
91   {
92   case 'a': return AREG;
93   case 'b': return BREG;
94   case 'c': return CREG;
95   case 'd': return DREG;
96   case 'S': return SIREG;
97   case 'D': return DIREG;
98   case 'B': return BPREG;
99   case 'r': return GENERAL_REGS;
100   case 'q': return Q_REGS;
101   }
102   return NO_REGS;
103 }
104
105 int
106 i86_const_ok_for_letter_p(int v, int c)
107 {
108   switch (c)
109   {
110   case 'I':
111     /* The constant that we can shift by: shl ax,1 */
112     return v >= 0 && v <= 31;
113   case 'J':
114     /* I/O ports and byte registers */
115     return v >= 0 && v <= 255;
116   }
117   return 0;
118 }
119
120 /* The purpose of this function is to decide if "x" represents
121    an addressing mode that the assembler can handle directly.  If
122    not, gcc will simplify it.
123
124 */
125
126 #define DEBUG 0
127
128 /* g: general-purpose
129    b: base
130    i: index
131    s: stack
132
133    ax dx cx bx si di bp sp
134 */
135 static char packreg[] = "gugugubuiuiubusu";
136 static char *
137 pack_rtx(rtx r, char *buf, char *ebuf, int strict)
138 {
139   if (buf >= ebuf)
140     return buf;
141   switch (GET_CODE(r))
142   {
143   case PLUS:
144     *buf++ = '+';
145     buf = pack_rtx(XEXP(r,0), buf, ebuf, strict);
146     buf = pack_rtx(XEXP(r,1), buf, ebuf, strict);
147     break;
148   case MEM:
149     *buf++ = 'm';
150     buf = pack_rtx(XEXP(r,0), buf, ebuf, strict);
151     break;
152   case PRE_DEC:
153     *buf++ = '<';
154     buf = pack_rtx(XEXP(r,0), buf, ebuf, strict);
155     break;
156   case REG:
157     if (strict || REGNO(r)<FIRST_PSEUDO_REGISTER)
158       *buf++ = REGNO(r) >= FIRST_PSEUDO_REGISTER ? '?' : packreg[REGNO(r)];
159     else
160       *buf++ = 'p';
161     break;
162   case CONST:
163   case CONST_INT:
164   case SYMBOL_REF:
165     *buf++ = '#';
166     break;
167   default:
168     *buf++ = '?';
169     break;
170   }
171   return buf;
172 }
173
174 static const char *valid_addr_list[] = {
175   "#",
176   "b",
177   "i",
178   "p",
179   "+bi",
180   "+ib",
181   "+pi",
182   "+ip",
183   "+pb",
184   "+bp",
185   "+pp",
186   "+b#",
187   "+i#",
188   "+p#",
189   "++bi#",
190   "++ib#",
191   "++pi#",
192   "++ip#",
193   "++pb#",
194   "++bp#",
195   "++pp#",
196   "<s",
197   "<p",
198   0
199 };
200
201 int
202 i86_valid_addr(enum machine_mode mode ATTRIBUTE_UNUSED, rtx x, int strict)
203 {
204   int i;
205   char packed[20];
206   *pack_rtx(x, packed, packed+20, strict) = 0;
207 #if DEBUG
208   print_rtl(stdout, x);
209   printf(" mode %s %s: `%s'   ", mode_name[mode], strict?"strict":"", packed);
210 #endif
211
212   for (i=0; valid_addr_list[i]; i++)
213   {
214     const char *v = valid_addr_list[i];
215     if (*v == '!')
216     {
217       if (strict)
218         continue;
219       v++;
220     }
221     if (strcmp(packed, v) == 0)
222     {
223 #if DEBUG
224       printf("yup\n");
225 #endif
226       return 1;
227     }
228   }
229 #if DEBUG
230   printf("nope\n");
231 #endif
232   return 0;
233 }
234
235 void
236 i86_notice_update_cc(rtx e ATTRIBUTE_UNUSED)
237 {
238   CC_STATUS_INIT;
239 }
240
241
242 /* Generate a "push" pattern for input ARG.  */
243 static rtx
244 gen_push (rtx arg, enum machine_mode mode)
245 {
246   return gen_rtx_SET (VOIDmode,
247                       gen_rtx_MEM (mode,
248                                    gen_rtx_PRE_DEC (Pmode,
249                                                     stack_pointer_rtx)),
250                       arg);
251 }
252
253 static int
254 i86_need_save (int regno)
255 {
256   return df_regs_ever_live_p (regno) && ! call_used_regs[regno];
257 }
258
259 void
260 i86_expand_prologue (void)
261 {
262   rtx insn;
263   int regno;
264   HOST_WIDE_INT size = get_frame_size ();
265
266   /* Enter is 4 bytes, the normal prologue is 3 bytes if size
267      is zero, otherwise 5 or 6 bytes. */
268   if (size) {
269     insn = emit_insn (gen_enterhi1 (gen_int_mode (size, Pmode)));
270     RTX_FRAME_RELATED_P (insn) = 1;
271   } else {
272     insn = emit_insn (gen_push (hard_frame_pointer_rtx, Pmode));
273     RTX_FRAME_RELATED_P (insn) = 1;
274
275     insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
276     RTX_FRAME_RELATED_P (insn) = 1;
277
278 #if 0
279     /* This code is unreachable, since enter is always used. */
280     if (size) {
281       insn = emit_insn (gen_subhi3 (stack_pointer_rtx, stack_pointer_rtx,
282                         gen_int_mode (size, Pmode)));
283       RTX_FRAME_RELATED_P (insn) = 1;
284     }
285 #endif
286   }
287
288   for (regno = REG_DI; regno >= REG_AX; regno -= 2) {
289     if (i86_need_save (regno+1)) {
290       insn = emit_insn (gen_push (gen_rtx_REG (SImode, regno), SImode));
291       RTX_FRAME_RELATED_P (insn) = 1;
292     } else if (i86_need_save (regno)) {
293       insn = emit_insn (gen_push (gen_rtx_REG (HImode, regno), HImode));
294       RTX_FRAME_RELATED_P (insn) = 1;
295     }
296   }    
297 }
298
299 void
300 i86_expand_epilogue (int style)
301 {
302   int regno;
303
304   for (regno = REG_AX; regno <= REG_DI; regno += 2) {
305     if (i86_need_save (regno+1)) {
306       emit_insn(gen_popsi1 (gen_rtx_REG (SImode, regno)));
307     } else if (i86_need_save (regno)) {
308       emit_insn(gen_pophi1 (gen_rtx_REG (HImode, regno)));
309     }
310   }
311
312   emit_insn (gen_leavehi ());
313
314   /* If style == 0 then this is a sibcall; no return instruction */
315   if (style)
316     emit_jump_insn (gen_return_internal ());
317 }
318
319 #undef DEBUG
320 #define DEBUG 1
321
322 static void
323 print_reg (rtx x, int c, FILE *s)
324 {
325   enum machine_mode mode = GET_MODE (x);
326
327   gcc_assert (GET_CODE(x) == REG);
328
329   switch (c) {
330   case 'b':
331   case 'L':
332   case 'H':
333     mode = QImode;
334     break;
335   case 'w':
336     mode = HImode;
337     break;
338   case 'd':
339   case 'D':
340     mode = SImode;
341     break;
342   case 'q':                     /* First DImode register */
343     mode = DImode;
344     break;
345   default:
346     break;
347   }
348   
349   switch (mode) {
350   case QImode:
351     gcc_assert (REGNO(x) < REG_SI);
352     fprintf (s, "%%%c%c", register_names[REGNO(x)][0],
353              (c == 'H') ? 'h' : 'l');
354     break;
355   case HImode:
356     fprintf (s, "%%%s", register_names[REGNO(x)]);
357     break;
358   case SImode:
359   case DImode:
360     {
361       int nr = (c == 'D') ? 2 : 0;
362       fprintf (s, "%%e%s", register_names[REGNO(x)+nr]);
363     }
364     break;
365   default:
366     gcc_unreachable ();
367   }
368 }
369
370 void
371 i86_print_operand(FILE *s, rtx x, int c)
372 {
373 #if DEBUG
374   printf("[i86_print_operand(%c)]\n", c?c:' ');
375   print_rtl(stdout, x);
376   printf("\n");
377 #endif
378   switch (GET_CODE (x))
379   {
380   case REG:
381     print_reg (x, c, s);
382     break;
383     break;
384
385   case MEM:
386     x = XEXP (x,0);
387     if (c == 'P') {
388       i86_print_operand(s, x, 0);
389     } else {
390       if (c == 'D')
391         fprintf (s, "4+");
392       i86_print_operand_address(s, x);
393     }
394     break;
395
396   case PLUS:
397     i86_print_operand(s, XEXP(x,0), 0);
398     if (GET_CODE(XEXP(x,1)) == CONST_INT)
399     {
400       fprintf(s, "%+d", (int)INTVAL(XEXP(x,1))); /* offset */
401     }
402     else
403     {
404       fputc('+', s);
405       i86_print_operand(s, XEXP(x,1), 0);
406     }
407     break;
408   case SYMBOL_REF:
409     assemble_name(s, XSTR(x,0));
410     break;
411   case CONST:
412   case CONST_INT:
413   case CODE_LABEL:
414     fputc('$', s);
415     output_addr_const(s, x);
416     break;
417   default:
418     printf("blah! default in i86_print_operand %d\n", GET_CODE(x));
419     break;
420     }
421 }
422
423 struct i86_address {
424   rtx base;
425   rtx index;
426   rtx disp;
427 };
428
429 /* Heavily cribbed from i386 ix86_decompose_address() */
430 static int
431 i86_decompose_address (rtx addr, struct i86_address *out)
432 {
433   rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
434   rtx base_reg, index_reg;
435   int retval = 1;
436   
437   if (REG_P (addr) || GET_CODE (addr) == SUBREG)
438     base = addr;
439   else if (GET_CODE (addr) == PLUS)
440     {
441       rtx addends[3], op;
442       int n = 0, i;
443
444       op = addr;
445       do
446         {
447           if (n >= 3)
448             return 0;
449           addends[n++] = XEXP (op, 1);
450           op = XEXP (op, 0);
451         }
452
453       while (GET_CODE (op) == PLUS);
454       if (n >= 3)
455         return 0;
456       addends[n] = op;
457
458       for (i = n; i >= 0; --i)
459         {
460           op = addends[i];
461           switch (GET_CODE (op))
462             {
463             case REG:
464             case SUBREG:
465               if (!base)
466                 base = op;
467               else if (!index)
468                 index = op;
469               else
470                 return 0;
471               break;
472
473             case CONST:
474             case CONST_INT:
475             case SYMBOL_REF:
476             case LABEL_REF:
477               if (disp)
478                 return 0;
479               disp = op;
480               break;
481
482             default:
483               return 0;
484             }
485         }
486     }
487   else
488     disp = addr;                        /* displacement */
489
490   base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
491   index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
492
493   /* Special case: (%bp) can only be encoded as 0(%bp).  The assembler
494      would do the right thing, but cost accounting would be off. */
495   if ((base_reg == hard_frame_pointer_rtx
496        || base_reg == frame_pointer_rtx
497        || base_reg == arg_pointer_rtx) && !disp)
498     disp = const0_rtx;
499
500   out->base = base_reg;
501   out->index = index;
502   out->disp = disp;
503
504   return retval;
505 }
506
507 void
508 i86_print_operand_address(FILE *s, rtx x)
509 {
510   struct i86_address parts;
511   rtx base, index, disp;
512   int ok = i86_decompose_address (x, &parts);
513
514 #if DEBUG
515   printf("[i86_print_operand_address] ok = %d\n", ok);
516   print_rtl(stdout, x);
517   printf("\n");
518 #endif
519
520   gcc_assert (ok);
521
522   base = parts.base;
523   index = parts.index;
524   disp = parts.disp;
525
526 #if DEBUG
527   printf("base =\n");
528   print_rtl(stdout, base);
529   printf("index =\n");
530   print_rtl(stdout, index);
531   printf("disp =\n");
532   print_rtl(stdout, disp);
533 #endif
534
535   if (disp) {
536     if (GET_CODE (disp) == LABEL_REF)
537       output_asm_label (disp);
538     else
539       output_addr_const (s, disp);
540   }
541
542   if (base || index) {
543     putc ('(', s);
544     if (base)
545       print_reg (base, 0, s);
546     if (index) {
547       putc(',', s);
548       print_reg (index, 0, s);
549     }
550     putc (')', s);
551   }
552 }
553
554 static void
555 i86_file_start (void)
556 {
557   default_file_start ();
558
559   fprintf (asm_out_file, "\t.code16\n\n");
560 }
561
562 static rtx
563 i86_function_value (tree valtype, tree fntype_or_decl ATTRIBUTE_UNUSED,
564                      bool outgoing ATTRIBUTE_UNUSED)
565 {
566   /* return everything in %ax (FIXME) */
567   return gen_rtx_REG (TYPE_MODE( valtype ), REG_AX);
568 }
569
570
571 /* Return the cost of moving data from a register in class CLASS1 to
572    one in class CLASS2.
573
574    It is not required that the cost always equal 2 when FROM is the same as TO;
575    on some machines it is expensive to move between registers if they are not
576    general registers.  */
577
578 int
579 i86_register_move_cost (enum machine_mode mode, enum reg_class class1,
580                          enum reg_class class2)
581 {
582   return 2;
583 }
584
585
586 /* Return the cost of moving data of mode M between a
587    register and memory.  A value of 2 is the default; this cost is
588    relative to those in `REGISTER_MOVE_COST'.
589
590    If moving between registers and memory is more expensive than
591    between two registers, you should define this macro to express the
592    relative cost.
593
594    Model also increased moving costs of QImode registers in non
595    Q_REGS classes.
596  */
597 int
598 i86_memory_move_cost (enum machine_mode mode, enum reg_class regclass, int in)
599 {
600   if (mode == SImode)
601     return 3;
602   else
603     return 2;
604 }
605
606
607 /* Compute a (partial) cost for rtx X.  Return true if the complete
608    cost has been computed, and false if subexpressions should be
609    scanned.  In either case, *TOTAL contains the cost result.  */
610
611 static bool
612 i86_rtx_costs (rtx x, int code, int outer_code_i, int *total)
613 {
614   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
615   enum machine_mode mode = GET_MODE (x);
616
617   switch (code)
618     {
619     case CONST_INT:
620     case CONST:
621     case LABEL_REF:
622     case SYMBOL_REF:
623       *total = GET_MODE_SIZE (mode);
624       return true;
625
626     case ZERO_EXTEND:
627     case SIGN_EXTEND:
628       if (mode == SImode)
629         *total = 4;
630       else
631         *total = 3;
632       return true;
633
634     default:
635       return false;
636     }
637 }
638
639