View | Details | Raw Unified | Return to bug 21683
Collapse All | Expand All

(-)a/gas/config/tc-avr.c (-7 / +601 lines)
Lines 23-28 Link Here
23
#include "as.h"
23
#include "as.h"
24
#include "safe-ctype.h"
24
#include "safe-ctype.h"
25
#include "subsegs.h"
25
#include "subsegs.h"
26
#include "struc-symbol.h"
26
#include "dwarf2dbg.h"
27
#include "dwarf2dbg.h"
27
#include "dw2gencfi.h"
28
#include "dw2gencfi.h"
28
#include "elf/avr.h"
29
#include "elf/avr.h"
Lines 54-59 struct avr_opcodes_s avr_opcodes[] = Link Here
54
  {NULL, NULL, NULL, 0, 0, 0}
55
  {NULL, NULL, NULL, 0, 0, 0}
55
};
56
};
56
57
58
59
/* Stuff for the `__gcc_isr' pseudo instruction.
60
61
   Purpose of the pseudo instruction is to emit more efficient ISR prologues
62
   and epilogues than GCC currently does.  GCC has no explicit (on RTL level)
63
   modelling of SREG, TMP_REG or ZERO_REG.  These regs are used implicitly
64
   during instruction printing.  That doesn't hurt too much for ordinary
65
   functions, however for small ISRs there might be some overhead.
66
67
   As implementing http://gcc.gnu.org/PR20296 would imply an almost complete
68
   rewite of GCC's AVR back-end (which might pop up less optimized code in
69
   other places), we provide a pseudo-instruction which is resolved by GAS
70
   into ISR prologue / epilogue as expected by GCC.
71
72
   Using GAS for this purpose has the additional benefit that it can scan
73
   code emit by inline asm which is opaque to GCC.
74
75
   The pseudo-instruction is only supposed to handle the starting of
76
   prologue and the ending of epilogues (without RETI) which deal with
77
   SREG, TMP_REG and ZERO_REG and one additional, optional general purpose
78
   register.
79
80
   __gcc_isr consists of 3 different "chunks":
81
82
   __gcc_isr 1
83
	Chunk 1 (ISR_CHUNK_Prologue)
84
	Start the ISR code.  Will be replaced by ISR prologue by next Done chunk.
85
	Must be the 1st chunk in a file or follow a Done chunk from previous
86
	ISR (which has been patched already).
87
88
	It will finish the current frag and emit a new frag of
89
	type rs_machine_dependent, subtype ISR_CHUNK_Prologue.
90
91
   __gcc_isr 2
92
	Chunk 2 (ISR_CHUNK_Epilogue)
93
	Will be replaced by ISR epilogue by next Done chunk. Must follow
94
	chunk 1 (Prologue) or chunk 2 (Epilogue).  Funktions might come
95
	without epilogue or with more than one epilogue, and even code
96
	located statically after the last epologue might belong to a function.
97
98
	It will finish the current frag and emit a new frag of
99
	type rs_machine_dependent, subtype ISR_CHUNK_Epilogue.
100
101
   __gcc_isr 0, Rx
102
	Chunk 0 (ISR_CHUNK_Done)
103
	Must follow chunk 1 (Prologue) or chunk 2 (Epilogue) and finishes
104
	the ISR code.  Only GCC can know where a function's code ends.
105
106
	It triggers the patch-up of all rs_machine_dependent frags in the
107
	current frag chain and turns them into ordinary rs_fill code frags.
108
109
	If Rx is a register > ZERO_REG then GCC also wants to push / pop Rx.
110
	If neither TMP_REG nor ZERO_REG are needed, Rx will be used in
111
	the push / pop sequence avoiding the need for TMP_REG / ZERO_REG.
112
	If Rx <= ZERO_REG then GCC doesn't assume anything about Rx.
113
114
   Assumptions:
115
116
	o  GCC takes care of code that is opaque to GAS like tail calls
117
	or non-local goto.
118
119
	o  Using SEI / CLI does not count as clobbering SREG.  This is
120
	because a final RETI will restore the I-flag.
121
122
	o  Using OUT or ST* is supposed not to clobber SREG.  Sequences like
123
124
		IN-SREG  +  CLI  +  Atomic-Code  +  OUT-SREG
125
126
	will still work as expected because the scan will reveal any
127
	clobber of SREG other than I-flag and emit PUSH / POP of SREG.
128
129
	o  If there is no epilogue, the prologue won't be optimized and
130
	"classic" prologue will be emit.  */
131
132
enum
133
  {
134
    ISR_CHUNK_Done = 0,
135
    ISR_CHUNK_Prologue = 1,
136
    ISR_CHUNK_Epilogue = 2
137
  };
138
139
static struct
140
{
141
  /* Previous __gcc_isr chunk (one of the enums above or 0),
142
     and it's location for diagnostics.  */
143
  int prev_chunk;
144
  unsigned line;
145
  const char *file;
146
  /* Replacer for __gcc_isr.n_pushed once we know how many regs are
147
     pushed by the Prologue chunk.  */
148
  symbolS *sym_n_pushed;
149
150
  /* Set and used during parse from chunk 1 (Prologue) up to chunk 0 (Done).
151
     Set by `avr_update_gccisr' and used by `avr_patch_gccisr_frag'.  */
152
  int need_reg_tmp;
153
  int need_reg_zero;
154
  int need_sreg;
155
  int n_epilogues;
156
} avr_isr;
157
158
static void avr_gccisr_operands (struct avr_opcodes_s*, char**);
159
static void avr_update_gccisr (struct avr_opcodes_s*, int, int);
160
static struct avr_opcodes_s *avr_gccisr_opcode;
161
57
const char comment_chars[] = ";";
162
const char comment_chars[] = ";";
58
const char line_comment_chars[] = "#";
163
const char line_comment_chars[] = "#";
59
const char line_separator_chars[] = "$";
164
const char line_separator_chars[] = "$";
Lines 359-367 struct avr_opt_s Link Here
359
  int no_wrap;      /* -mno-wrap: reject rjmp/rcall with 8K wrap-around.  */
464
  int no_wrap;      /* -mno-wrap: reject rjmp/rcall with 8K wrap-around.  */
360
  int no_link_relax;   /* -mno-link-relax / -mlink-relax: generate (or not)
465
  int no_link_relax;   /* -mno-link-relax / -mlink-relax: generate (or not)
361
                          relocations for linker relaxation.  */
466
                          relocations for linker relaxation.  */
467
  int have_gccisr;      /* Whether "__gcc_isr" is a known (pseudo) insn.  */
362
};
468
};
363
469
364
static struct avr_opt_s avr_opt = { 0, 0, 0, 0 };
470
static struct avr_opt_s avr_opt = { 0, 0, 0, 0, 0 };
365
471
366
const char EXP_CHARS[] = "eE";
472
const char EXP_CHARS[] = "eE";
367
const char FLT_CHARS[] = "dD";
473
const char FLT_CHARS[] = "dD";
Lines 416-421 static struct hash_control *avr_hash; Link Here
416
/* Reloc modifiers hash control (hh8,hi8,lo8,pm_xx).  */
522
/* Reloc modifiers hash control (hh8,hi8,lo8,pm_xx).  */
417
static struct hash_control *avr_mod_hash;
523
static struct hash_control *avr_mod_hash;
418
524
525
/* Whether some opcode does not change SREG.  */
526
static struct hash_control *avr_no_sreg_hash;
527
528
static const char* const avr_no_sreg[] =
529
  {
530
    /* Arithmetic */
531
    "ldi", "swap", "mov", "movw",
532
    /* Special instructions.  I-Flag will be restored by RETI, and we don't
533
       consider I-Flag as being clobbered when changed.  */
534
    "sei", "cli", "reti", "brie", "brid",
535
    "nop", "wdr", "sleep",
536
    /* Load / Store */
537
    "ld", "ldd", "lds", "pop",  "in", "lpm", "elpm",
538
    "st", "std", "sts", "push", "out",
539
    /* Jumps and Calls.  Calls might call code that changes SREG.
540
       GCC has to filter out ABI calls.  The non-ABI transparent calls
541
       must use [R]CALL and are filtered out now by not mentioning them.  */
542
    "rjmp", "jmp", "ijmp", "ret",
543
    /* Skipping.  Branches need SREG to be set, hence we regard them
544
       as if they changed SREG and don't list them here.  */
545
    "sbrc", "sbrs", "sbic", "sbis", "cpse",
546
    /* I/O Manipulation */
547
    "sbi", "cbi",
548
    /* Read-Modify-Write */
549
    "lac", "las", "lat", "xch"
550
  };
551
419
#define OPTION_MMCU 'm'
552
#define OPTION_MMCU 'm'
420
enum options
553
enum options
421
{
554
{
Lines 424-430 enum options Link Here
424
  OPTION_NO_WRAP,
557
  OPTION_NO_WRAP,
425
  OPTION_ISA_RMW,
558
  OPTION_ISA_RMW,
426
  OPTION_LINK_RELAX,
559
  OPTION_LINK_RELAX,
427
  OPTION_NO_LINK_RELAX
560
  OPTION_NO_LINK_RELAX,
561
  OPTION_HAVE_GCCISR
428
};
562
};
429
563
430
struct option md_longopts[] =
564
struct option md_longopts[] =
Lines 436-441 struct option md_longopts[] = Link Here
436
  { "mrmw",         no_argument, NULL, OPTION_ISA_RMW     },
570
  { "mrmw",         no_argument, NULL, OPTION_ISA_RMW     },
437
  { "mlink-relax",  no_argument, NULL, OPTION_LINK_RELAX  },
571
  { "mlink-relax",  no_argument, NULL, OPTION_LINK_RELAX  },
438
  { "mno-link-relax",  no_argument, NULL, OPTION_NO_LINK_RELAX  },
572
  { "mno-link-relax",  no_argument, NULL, OPTION_NO_LINK_RELAX  },
573
  { "mgcc-isr",     no_argument, NULL, OPTION_HAVE_GCCISR },
439
  { NULL, no_argument, NULL, 0 }
574
  { NULL, no_argument, NULL, 0 }
440
};
575
};
441
576
Lines 544-549 md_show_usage (FILE *stream) Link Here
544
	"  -mrmw            accept Read-Modify-Write instructions\n"
679
	"  -mrmw            accept Read-Modify-Write instructions\n"
545
	"  -mlink-relax     generate relocations for linker relaxation (default)\n"
680
	"  -mlink-relax     generate relocations for linker relaxation (default)\n"
546
	"  -mno-link-relax  don't generate relocations for linker relaxation.\n"
681
	"  -mno-link-relax  don't generate relocations for linker relaxation.\n"
682
	"  -mgcc-isr        accept the __gcc_isr pseudo-instruction.\n"
547
        ));
683
        ));
548
  show_mcu_list (stream);
684
  show_mcu_list (stream);
549
}
685
}
Lines 610-623 md_parse_option (int c, const char *arg) Link Here
610
    case OPTION_NO_LINK_RELAX:
746
    case OPTION_NO_LINK_RELAX:
611
      avr_opt.no_link_relax = 1;
747
      avr_opt.no_link_relax = 1;
612
      return 1;
748
      return 1;
749
    case OPTION_HAVE_GCCISR:
750
      avr_opt.have_gccisr = 1;
751
      return 1;
613
    }
752
    }
614
753
615
  return 0;
754
  return 0;
616
}
755
}
617
756
757
758
/* Implement `md_undefined_symbol' */
759
/* If we are in `__gcc_isr' chunk, pop up `__gcc_isr.n_pushed.<NUM>' instead
760
   of `__gcc_isr.n_pushed'.  This will be resolved by the Done chunk to
761
   the number of PUSHes produced by the Prologue chunk.  */
762
618
symbolS *
763
symbolS *
619
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
764
avr_undefined_symbol (char *name)
620
{
765
{
766
  if (ISR_CHUNK_Done != avr_isr.prev_chunk
767
      && name[0] == '_' && name[1] == '_'
768
      && 0 == strcmp (name, "__gcc_isr.n_pushed"))
769
    {
770
      if (!avr_isr.sym_n_pushed)
771
	{
772
	  static int suffix;
773
	  char xname[30];
774
	  sprintf (xname, "%s.%u", name, ++suffix);
775
	  avr_isr.sym_n_pushed = symbol_new (xname, undefined_section,
776
					     (valueT) 0, &zero_address_frag);
777
	}
778
      return avr_isr.sym_n_pushed;
779
    }
780
621
  return NULL;
781
  return NULL;
622
}
782
}
623
783
Lines 659-664 md_begin (void) Link Here
659
      hash_insert (avr_mod_hash, EXP_MOD_NAME (i), m.ptr);
819
      hash_insert (avr_mod_hash, EXP_MOD_NAME (i), m.ptr);
660
    }
820
    }
661
821
822
  avr_no_sreg_hash = hash_new ();
823
824
  for (i = 0; i < ARRAY_SIZE (avr_no_sreg); ++i)
825
    {
826
      gas_assert (hash_find (avr_hash, avr_no_sreg[i]));
827
      hash_insert (avr_no_sreg_hash, avr_no_sreg[i], (char*) 4 /* dummy */);
828
    }
829
830
  avr_gccisr_opcode = (struct avr_opcodes_s*) hash_find (avr_hash, "__gcc_isr");
831
  gas_assert (avr_gccisr_opcode);
832
662
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach);
833
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach);
663
  linkrelax = !avr_opt.no_link_relax;
834
  linkrelax = !avr_opt.no_link_relax;
664
}
835
}
Lines 855-861 static unsigned int Link Here
855
avr_operand (struct avr_opcodes_s *opcode,
1026
avr_operand (struct avr_opcodes_s *opcode,
856
	     int where,
1027
	     int where,
857
	     const char *op,
1028
	     const char *op,
858
	     char **line)
1029
	     char **line,
1030
	     int *pregno)
859
{
1031
{
860
  expressionS op_expr;
1032
  expressionS op_expr;
861
  unsigned int op_mask = 0;
1033
  unsigned int op_mask = 0;
Lines 904-909 avr_operand (struct avr_opcodes_s *opcode, Link Here
904
          }
1076
          }
905
      }
1077
      }
906
1078
1079
      if (pregno)
1080
	*pregno = op_mask;
1081
907
      if (avr_mcu->mach == bfd_mach_avrtiny)
1082
      if (avr_mcu->mach == bfd_mach_avrtiny)
908
        {
1083
        {
909
          if (op_mask < 16 || op_mask > 31)
1084
          if (op_mask < 16 || op_mask > 31)
Lines 1079-1084 avr_operand (struct avr_opcodes_s *opcode, Link Here
1079
      }
1254
      }
1080
      break;
1255
      break;
1081
1256
1257
    case 'N':
1258
      {
1259
	unsigned int x;
1260
1261
	x = avr_get_constant (str, 255);
1262
	str = input_line_pointer;
1263
	op_mask = x;
1264
      }
1265
      break;
1266
1082
    case 'K':
1267
    case 'K':
1083
      input_line_pointer = str;
1268
      input_line_pointer = str;
1084
      avr_offset_expression (& op_expr);
1269
      avr_offset_expression (& op_expr);
Lines 1145-1150 avr_operands (struct avr_opcodes_s *opcode, char **line) Link Here
1145
  char *str = *line;
1330
  char *str = *line;
1146
  int where = frag - frag_now->fr_literal;
1331
  int where = frag - frag_now->fr_literal;
1147
  static unsigned int prev = 0;  /* Previous opcode.  */
1332
  static unsigned int prev = 0;  /* Previous opcode.  */
1333
  int regno1 = -2;
1334
  int regno2 = -2;
1148
1335
1149
  /* Opcode have operands.  */
1336
  /* Opcode have operands.  */
1150
  if (*op)
1337
  if (*op)
Lines 1157-1163 avr_operands (struct avr_opcodes_s *opcode, char **line) Link Here
1157
      /* Parse first operand.  */
1344
      /* Parse first operand.  */
1158
      if (REGISTER_P (*op))
1345
      if (REGISTER_P (*op))
1159
	reg1_present = 1;
1346
	reg1_present = 1;
1160
      reg1 = avr_operand (opcode, where, op, &str);
1347
      reg1 = avr_operand (opcode, where, op, &str, &regno1);
1161
      ++op;
1348
      ++op;
1162
1349
1163
      /* Parse second operand.  */
1350
      /* Parse second operand.  */
Lines 1170-1175 avr_operands (struct avr_opcodes_s *opcode, char **line) Link Here
1170
	    {
1357
	    {
1171
	      reg2 = reg1;
1358
	      reg2 = reg1;
1172
	      reg2_present = 1;
1359
	      reg2_present = 1;
1360
	      regno2 = regno1;
1173
	    }
1361
	    }
1174
	  else
1362
	  else
1175
	    {
1363
	    {
Lines 1181-1187 avr_operands (struct avr_opcodes_s *opcode, char **line) Link Here
1181
		as_bad (_("`,' required"));
1369
		as_bad (_("`,' required"));
1182
	      str = skip_space (str);
1370
	      str = skip_space (str);
1183
1371
1184
	      reg2 = avr_operand (opcode, where, op, &str);
1372
	      reg2 = avr_operand (opcode, where, op, &str, &regno2);
1185
	    }
1373
	    }
1186
1374
1187
	  if (reg1_present && reg2_present)
1375
	  if (reg1_present && reg2_present)
Lines 1194-1199 avr_operands (struct avr_opcodes_s *opcode, char **line) Link Here
1194
      bin |= reg1 | reg2;
1382
      bin |= reg1 | reg2;
1195
    }
1383
    }
1196
1384
1385
  if (avr_opt.have_gccisr)
1386
    avr_update_gccisr (opcode, regno1, regno2);
1387
1197
  /* Detect undefined combinations (like ld r31,Z+).  */
1388
  /* Detect undefined combinations (like ld r31,Z+).  */
1198
  if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin))
1389
  if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin))
1199
    as_warn (_("undefined combination of operands"));
1390
    as_warn (_("undefined combination of operands"));
Lines 1698-1703 md_assemble (char *str) Link Here
1698
      return;
1889
      return;
1699
    }
1890
    }
1700
1891
1892
    if (opcode == avr_gccisr_opcode
1893
	&& !avr_opt.have_gccisr)
1894
    {
1895
      as_bad (_("pseudo instruction `%s' not supported"), op);
1896
      return;
1897
    }
1898
1701
  /* Special case for opcodes with optional operands (lpm, elpm) -
1899
  /* Special case for opcodes with optional operands (lpm, elpm) -
1702
     version with operands exists in avr_opcodes[] in the next entry.  */
1900
     version with operands exists in avr_opcodes[] in the next entry.  */
1703
1901
Lines 1711-1717 md_assemble (char *str) Link Here
1711
  {
1909
  {
1712
    char *t = input_line_pointer;
1910
    char *t = input_line_pointer;
1713
1911
1714
    avr_operands (opcode, &str);
1912
    if (opcode == avr_gccisr_opcode)
1913
      avr_gccisr_operands (opcode, &str);
1914
    else
1915
      avr_operands (opcode, &str);
1715
    if (*skip_space (str))
1916
    if (*skip_space (str))
1716
      as_bad (_("garbage at end of line"));
1917
      as_bad (_("garbage at end of line"));
1717
    input_line_pointer = t;
1918
    input_line_pointer = t;
Lines 2211-2213 avr_post_relax_hook (void) Link Here
2211
{
2412
{
2212
  avr_create_and_fill_property_section ();
2413
  avr_create_and_fill_property_section ();
2213
}
2414
}
2415
2416
2417
/* Accumulate information about instruction sequence to `avr_isr':
2418
   wheter TMP_REG, ZERO_REG and SREG might be touched.  Used during parse.
2419
   REG1 is either -1 or a register number used by the instruction as input
2420
   or output operand.  Similar for REG2.  */
2421
2422
static void
2423
avr_update_gccisr (struct avr_opcodes_s *opcode, int reg1, int reg2)
2424
{
2425
  const int tiny_p = avr_mcu->mach == bfd_mach_avrtiny;
2426
  const int reg_tmp = tiny_p ? 16 : 0;
2427
  const int reg_zero = 1 + reg_tmp;
2428
2429
  if (ISR_CHUNK_Done == avr_isr.prev_chunk
2430
      || (avr_isr.need_sreg
2431
	  && avr_isr.need_reg_tmp
2432
	  && avr_isr.need_reg_zero))
2433
    {
2434
      /* Nothing (more) to do */
2435
      return;
2436
    }
2437
2438
  /* SREG: Look up instructions that don't clobber SREG.  */
2439
2440
  if (!avr_isr.need_sreg
2441
      && !hash_find (avr_no_sreg_hash, opcode->name))
2442
    {
2443
      avr_isr.need_sreg = 1;
2444
    }
2445
2446
  /* Handle explicit register operands.  Record *any* use as clobber.
2447
     This is because TMP_REG and ZERO_REG are not global and using
2448
     them makes no sense without a previous set.  */
2449
2450
  avr_isr.need_reg_tmp  |= reg1 == reg_tmp  || reg2 == reg_tmp;
2451
  avr_isr.need_reg_zero |= reg1 == reg_zero || reg2 == reg_zero;
2452
2453
  /* Handle implicit register operands and some opaque stuff.  */
2454
2455
  if (strstr (opcode->name, "lpm")
2456
      && '?' == *opcode->constraints)
2457
    {
2458
      avr_isr.need_reg_tmp = 1;
2459
    }
2460
2461
  if (strstr (opcode->name, "call")
2462
      || strstr (opcode->name, "mul")
2463
      || 0 == strcmp (opcode->name, "des")
2464
      || (0 == strcmp (opcode->name, "movw")
2465
	  && (reg1 == reg_tmp || reg2 == reg_tmp)))
2466
    {
2467
      avr_isr.need_reg_tmp = 1;
2468
      avr_isr.need_reg_zero = 1;
2469
    }
2470
}
2471
2472
2473
/* Emit some 1-word instruction to **PWHERE and advance *PWHERE by the number
2474
   of octets written.  INSN specifies the desired instruction and REG is the
2475
   register used by it.  This function is only used with restricted subset of
2476
   instructions as might be emit by `__gcc_isr'.  IN / OUT will use SREG
2477
   and LDI loads 0.  */
2478
2479
static void
2480
avr_emit_insn (const char *insn, int reg, char **pwhere)
2481
{
2482
  const int sreg = 0x3f;
2483
  unsigned bin = 0;
2484
  const struct avr_opcodes_s *op
2485
    = (struct avr_opcodes_s*) hash_find (avr_hash, insn);
2486
2487
  /* We only have to deal with: IN, OUT, PUSH, POP, CLR, LDI 0.  All of
2488
     these deal with at least one Reg and are 1-word instructions.  */
2489
2490
  gas_assert (op && 1 == op->insn_size);
2491
  gas_assert (reg >= 0 && reg <= 31);
2492
2493
  if (strchr (op->constraints, 'r'))
2494
    {
2495
      bin = op->bin_opcode | (reg << 4);
2496
    }
2497
  else if (strchr (op->constraints, 'd'))
2498
    {
2499
      gas_assert (reg >= 16);
2500
      bin = op->bin_opcode | ((reg & 0xf) << 4);
2501
    }
2502
  else
2503
    abort();
2504
2505
  if (strchr (op->constraints, 'P'))
2506
    {
2507
      bin |= ((sreg & 0x30) << 5) | (sreg & 0x0f);
2508
    }
2509
  else if (0 == strcmp ("r=r", op->constraints))
2510
    {
2511
      bin |= ((reg & 0x10) << 5) | (reg & 0x0f);
2512
    }
2513
  else
2514
    gas_assert (0 == strcmp ("r", op->constraints)
2515
		|| 0 == strcmp ("ldi", op->name));
2516
2517
  bfd_putl16 ((bfd_vma) bin, *pwhere);
2518
  (*pwhere) += 2 * op->insn_size;
2519
}
2520
2521
2522
/* Turn rs_machine_dependent frag *FR into an ordinary rs_fill code frag,
2523
   using information gathered in `avr_isr'.  REG is the register number as
2524
   supplied by Done chunk "__gcc_isr 0,REG".  */
2525
2526
static void
2527
avr_patch_gccisr_frag (fragS *fr, int reg)
2528
{
2529
  int treg;
2530
  int n_pushed = 0;
2531
  char *where = fr->fr_literal;
2532
  const int tiny_p = avr_mcu->mach == bfd_mach_avrtiny;
2533
  const int reg_tmp = tiny_p ? 16 : 0;
2534
  const int reg_zero = 1 + reg_tmp;
2535
2536
  if (ISR_CHUNK_Prologue == fr->fr_subtype
2537
      && 0 == avr_isr.n_epilogues)
2538
    {
2539
      avr_isr.need_reg_tmp = 1;
2540
      avr_isr.need_reg_zero = 1;
2541
      avr_isr.need_sreg = 1;
2542
    }
2543
2544
  /* Clearing ZERO_REG on non-Tiny needs CLR which clobbers SREG.  */
2545
2546
  avr_isr.need_sreg |= !tiny_p && avr_isr.need_reg_zero;
2547
2548
  /* A working register to PUSH / POP the SREG.  We might use the register
2549
     as supplied by ISR_CHUNK_Done for that purpose as GCC wants to push
2550
     it anyways.  If GCC passes ZERO_REG or TMP_REG, it has no clue (and
2551
     no additional regs to safe) and we use that reg.  */
2552
2553
  treg
2554
    = avr_isr.need_reg_tmp   ? reg_tmp
2555
    : avr_isr.need_reg_zero  ? reg_zero
2556
    : avr_isr.need_sreg      ? reg
2557
    : reg > reg_zero         ? reg
2558
    : -1;
2559
2560
  if (treg >= 0)
2561
    {
2562
      /* Non-empty prologue / epilogue */
2563
2564
      if (ISR_CHUNK_Prologue == fr->fr_subtype)
2565
	{
2566
	  avr_emit_insn ("push", treg, &where);
2567
	  n_pushed++;
2568
2569
	  if (avr_isr.need_sreg)
2570
	    {
2571
	      avr_emit_insn ("in",   treg, &where);
2572
	      avr_emit_insn ("push", treg, &where);
2573
	      n_pushed++;
2574
	    }
2575
2576
	  if (avr_isr.need_reg_zero)
2577
	    {
2578
	      if (reg_zero != treg)
2579
		{
2580
		  avr_emit_insn ("push", reg_zero, &where);
2581
		  n_pushed++;
2582
		}
2583
	      avr_emit_insn (tiny_p ? "ldi" : "clr", reg_zero, &where);
2584
	    }
2585
2586
	  if (reg > reg_zero && reg != treg)
2587
	    {
2588
	      avr_emit_insn ("push", reg, &where);
2589
	      n_pushed++;
2590
	    }
2591
	}
2592
      else if (ISR_CHUNK_Epilogue == fr->fr_subtype)
2593
	{
2594
	  /* Same logic as in Prologue but in reverse order and with counter
2595
	     parts of either instruction:  POP instead of PUSH and OUT instead
2596
	     of IN.  Clearing ZERO_REG has no couter part.  */
2597
2598
	  if (reg > reg_zero && reg != treg)
2599
	    avr_emit_insn ("pop", reg, &where);
2600
2601
	  if (avr_isr.need_reg_zero
2602
	      && reg_zero != treg)
2603
	    avr_emit_insn ("pop", reg_zero, &where);
2604
2605
	  if (avr_isr.need_sreg)
2606
	    {
2607
	      avr_emit_insn ("pop", treg, &where);
2608
	      avr_emit_insn ("out", treg, &where);
2609
	    }
2610
2611
	  avr_emit_insn ("pop", treg, &where);
2612
	}
2613
      else
2614
	abort();
2615
    } /* treg >= 0 */
2616
2617
  if (ISR_CHUNK_Prologue == fr->fr_subtype
2618
      && avr_isr.sym_n_pushed)
2619
    {
2620
      symbolS *sy = avr_isr.sym_n_pushed;
2621
      /* Turn magic `__gcc_isr.n_pushed' into its now known value.  */
2622
2623
      sy->sy_value.X_op = O_constant;
2624
      sy->sy_value.X_add_number = n_pushed;
2625
      S_SET_SEGMENT (sy, expr_section);
2626
      avr_isr.sym_n_pushed = NULL;
2627
    }
2628
2629
  /* Turn frag into ordinary code frag of now known size.  */
2630
2631
  fr->fr_var = 0;
2632
  fr->fr_fix = (offsetT) (where - fr->fr_literal);
2633
  gas_assert (fr->fr_fix <= fr->fr_offset);
2634
  fr->fr_offset = 0;
2635
  fr->fr_type = rs_fill;
2636
  fr->fr_subtype = 0;
2637
}
2638
2639
2640
/* Implements `__gcc_isr' pseudo-instruction.  For Prologue and Epilogue
2641
   chunks, emit a new rs_machine_dependent frag.  For Done chunks, traverse
2642
   the current segment and patch all rs_machine_dependent frags to become
2643
   appropriate rs_fill code frags.  If chunks are seen in an odd ordering,
2644
   throw an error instead.  */
2645
2646
static void
2647
avr_gccisr_operands (struct avr_opcodes_s *opcode, char **line)
2648
{
2649
  int bad = 0;
2650
  int chunk, reg = 0;
2651
  char *str = *line;
2652
2653
  gas_assert (avr_opt.have_gccisr);
2654
2655
  /* We only use operands "N" and "r" which don't pop new fix-ups.  */
2656
2657
  /* 1st operand: Which chunk of __gcc_isr: 0...2.  */
2658
2659
  chunk = avr_operand (opcode, -1, "N", &str, NULL);
2660
  if (chunk < 0 || chunk > 2)
2661
    as_bad (_("%s requires value 0-2 as operand 1"), opcode->name);
2662
2663
  if (ISR_CHUNK_Done == chunk)
2664
    {
2665
      /* 2nd operand: A register to push / pop.  */
2666
2667
      str = skip_space (str);
2668
      if (*str == '\0' || *str++ != ',')
2669
	as_bad (_("`,' required"));
2670
      else
2671
	avr_operand (opcode, -1, "r", &str, &reg);
2672
    }
2673
2674
  *line = str;
2675
2676
  /* Chunks must follow in a specific order:
2677
     - Prologue: Exactly one
2678
     - Epilogue: Any number
2679
     - Done: Exactly one.  */
2680
  bad |= ISR_CHUNK_Prologue == chunk && avr_isr.prev_chunk != ISR_CHUNK_Done;
2681
  bad |= ISR_CHUNK_Epilogue == chunk && avr_isr.prev_chunk == ISR_CHUNK_Done;
2682
  bad |= ISR_CHUNK_Done == chunk && avr_isr.prev_chunk == ISR_CHUNK_Done;
2683
  if (bad)
2684
    {
2685
      if (avr_isr.file)
2686
	as_bad (_("`%s %d' after `%s %d' from %s:%u"), opcode->name, chunk,
2687
		opcode->name, avr_isr.prev_chunk, avr_isr.file, avr_isr.line);
2688
      else
2689
	as_bad (_("`%s %d' but no chunk open yet"), opcode->name, chunk);
2690
    }
2691
2692
  if (!had_errors())
2693
    {
2694
      /* The longest sequence (prologue) might have up to 6 insns (words):
2695
2696
	 push  R0
2697
	 in    R0, SREG
2698
	 push  R0
2699
	 push  R1
2700
	 clr   R1
2701
	 push  Rx
2702
      */
2703
      unsigned int size = 2 * 6;
2704
      fragS *fr;
2705
2706
      switch (chunk)
2707
	{
2708
	case ISR_CHUNK_Prologue:
2709
	  avr_isr.need_reg_tmp = 0;
2710
	  avr_isr.need_reg_zero = 0;
2711
	  avr_isr.need_sreg = 0;
2712
	  avr_isr.sym_n_pushed = NULL;
2713
	  avr_isr.n_epilogues = -1;
2714
	  /* FALLTHRU */
2715
2716
	case ISR_CHUNK_Epilogue:
2717
	  avr_isr.n_epilogues++;
2718
2719
	  /* Emit a new rs_machine_dependent fragment into the fragment chain.
2720
	     It will be patched and cleaned up once we see the matching
2721
	     ISR_CHUNK_Done.  */
2722
	  frag_wane (frag_now);
2723
	  frag_new (0);
2724
	  frag_more (size);
2725
2726
	  frag_now->fr_var = 1;
2727
	  frag_now->fr_offset = size;
2728
	  frag_now->fr_fix = 0;
2729
	  frag_now->fr_type = rs_machine_dependent;
2730
	  frag_now->fr_subtype = chunk;
2731
	  frag_new (size);
2732
	  break;
2733
2734
	case ISR_CHUNK_Done:
2735
	  /* Traverse all frags of the current subseg and turn ones of type
2736
	     rs_machine_dependent into ordinary code as expected by GCC.  */
2737
2738
	  for (fr = frchain_now->frch_root; fr; fr = fr->fr_next)
2739
	    if (fr->fr_type == rs_machine_dependent)
2740
	      avr_patch_gccisr_frag (fr, reg);
2741
	  break;
2742
2743
	default:
2744
	  abort();
2745
	  break;
2746
	}
2747
    } /* !had_errors */
2748
2749
  avr_isr.prev_chunk = chunk;
2750
  avr_isr.file = as_where (&avr_isr.line);
2751
}
2752
2753
2754
/* Callback used by the function below.  Diagnose any dangling stuff from
2755
   `__gcc_isr', i.e. frags of type rs_machine_dependent.  Such frags should
2756
   have been resolved during parse by ISR_CHUNK_Done.  If such a frag is
2757
   seen, report an error and turn it into something harmless.  */
2758
2759
static void
2760
avr_check_gccisr_done (bfd *abfd ATTRIBUTE_UNUSED,
2761
		       segT section,
2762
		       void *xxx ATTRIBUTE_UNUSED)
2763
{
2764
  segment_info_type *info = seg_info (section);
2765
2766
  if (SEG_NORMAL (section)
2767
      /* BFD may have introduced its own sections without using
2768
	 subseg_new, so it is possible that seg_info is NULL.  */
2769
      && info)
2770
    {
2771
      fragS *fr;
2772
      frchainS *frch;
2773
2774
      for (frch = info->frchainP; frch; frch = frch->frch_next)
2775
	for (fr = frch->frch_root; fr; fr = fr->fr_next)
2776
	  if (fr->fr_type == rs_machine_dependent)
2777
	    {
2778
	      if (avr_isr.file)
2779
		as_bad_where (avr_isr.file, avr_isr.line,
2780
			      _("dangling `__gcc_isr %d'"), avr_isr.prev_chunk);
2781
	      else if (!had_errors())
2782
		as_bad (_("dangling `__gcc_isr'"));
2783
2784
	      avr_isr.file = NULL;
2785
2786
	      /* Avoid Internal errors due to rs_machine_dependent in the
2787
		 remainder:  Turn frag into something harmless.   */
2788
	      fr->fr_var = 0;
2789
	      fr->fr_fix = 0;
2790
	      fr->fr_offset = 0;
2791
	      fr->fr_type = rs_fill;
2792
	      fr->fr_subtype = 0;
2793
	    }
2794
    }
2795
}
2796
2797
2798
/* Implement `md_pre_output_hook' */
2799
/* Run over all relevant sections and diagnose any dangling `__gcc_isr'.
2800
   This runs after parsing all inputs but before relaxing and writing.  */
2801
2802
void
2803
avr_pre_output_hook (void)
2804
{
2805
  if (avr_opt.have_gccisr)
2806
    bfd_map_over_sections (stdoutput, avr_check_gccisr_done, NULL);
2807
}
(-)a/gas/config/tc-avr.h (+6 lines)
Lines 220-225 extern bfd_boolean avr_allow_local_subtract (expressionS *, expressionS *, segT) Link Here
220
#define elf_tc_final_processing 	avr_elf_final_processing
220
#define elf_tc_final_processing 	avr_elf_final_processing
221
extern void avr_elf_final_processing (void);
221
extern void avr_elf_final_processing (void);
222
222
223
#define md_pre_output_hook avr_pre_output_hook ()
224
extern void avr_pre_output_hook (void);
225
226
#define md_undefined_symbol avr_undefined_symbol
227
extern symbolS* avr_undefined_symbol (char*);
228
223
#define md_post_relax_hook avr_post_relax_hook ()
229
#define md_post_relax_hook avr_post_relax_hook ()
224
extern void avr_post_relax_hook (void);
230
extern void avr_post_relax_hook (void);
225
231
(-)a/gas/doc/c-avr.texi (+62 lines)
Lines 18-23 Link Here
18
* AVR Options::              Options
18
* AVR Options::              Options
19
* AVR Syntax::               Syntax
19
* AVR Syntax::               Syntax
20
* AVR Opcodes::              Opcodes
20
* AVR Opcodes::              Opcodes
21
* AVR Pseudo Instructions::  Pseudo Instructions
21
@end menu
22
@end menu
22
23
23
@node AVR Options
24
@node AVR Options
Lines 151-156 Disable support for link-time relaxation. The assembler will resolve Link Here
151
relocations when it can, and may be able to better compress some debug
152
relocations when it can, and may be able to better compress some debug
152
information.
153
information.
153
154
155
@cindex @code{-mgcc-isr} command line option, AVR
156
@item -mgcc-isr
157
Enable the @code{__gcc_isr} pseudo instruction.
158
154
@end table
159
@end table
155
160
156
161
Lines 441-443 The following table summarizes the AVR opcodes, and their arguments. Link Here
441
1001010100011001   eicall
446
1001010100011001   eicall
442
1001010000011001   eijmp
447
1001010000011001   eijmp
443
@end smallexample
448
@end smallexample
449
450
@node AVR Pseudo Instructions
451
@section Pseudo Instructions
452
453
The only available pseudo-instruction @code{__gcc_isr} can be activated by
454
option @option{-mgcc-isr}.
455
456
@table @code
457
458
@item __gcc_isr 1
459
Emit code chunk to be used in avr-gcc ISR prologue.
460
It will expand to at most six 1-word instructions, all optional:
461
push of @code{tmp_reg}, push of @code{SREG},
462
push and clear of @code{zero_reg}, push of @var{Reg}.
463
464
@item __gcc_isr 2
465
Emit code chunk to be used in an avr-gcc ISR epilogue.
466
It will expand to at most five 1-word instructions, all optional: 
467
pop of @var{Reg}, pop of @code{zero_reg},
468
pop of @code{SREG}, pop of @code{tmp_reg}.
469
470
@item __gcc_isr 0, @var{Reg}
471
Finish avr-gcc ISR function.  Scan code since the last prologue
472
for usage of: @code{SREG}, @code{tmp_reg}, @code{zero_reg}.
473
Prologue chunk and epilogue chunks will be replaced by appropriate code
474
to save / restore @code{SREG}, @code{tmp_reg}, @code{zero_reg} and @var{Reg}.
475
476
@end table
477
478
Example input:
479
480
@example
481
__vector1:
482
    __gcc_isr 1
483
    lds r24, var
484
    inc r24
485
    sts var, r24
486
    __gcc_isr 2
487
    reti
488
    __gcc_isr 0, r24
489
@end example
490
491
Example output:
492
493
@example
494
00000000 <__vector1>:
495
   0:   8f 93           push    r24
496
   2:   8f b7           in      r24, 0x3f
497
   4:   8f 93           push    r24
498
   6:   80 91 60 00     lds     r24, 0x0060     ; 0x800060 <var>
499
   a:   83 95           inc     r24
500
   c:   80 93 60 00     sts     0x0060, r24     ; 0x800060 <var>
501
  10:   8f 91           pop     r24
502
  12:   8f bf           out     0x3f, r24
503
  14:   8f 91           pop     r24
504
  16:   18 95           reti
505
@end example
(-)a/gas/testsuite/gas/avr/gccisr-01.d (+140 lines)
Line 0 Link Here
1
#name: gccisr-01: __gcc_isr pseudo instruction
2
#as: -mgcc-isr -mavr4
3
#objdump: -dz
4
#target: avr-*-*
5
6
.*: +file format elf32-avr
7
8
9
Disassembly of section \.text:
10
11
00000000 <__start1>:
12
   0:	68 94       	set
13
14
00000002 <__vec1_start>:
15
   2:	0f 92       	push	r0
16
   4:	0f b6       	in	r0, 0x3f	; 63
17
   6:	0f 92       	push	r0
18
   8:	1f 92       	push	r1
19
   a:	11 24       	eor	r1, r1
20
   c:	2f 92       	push	r2
21
   e:	e8 94       	clt
22
23
00000010 <__data1>:
24
  10:	00 e0       	ldi	r16, 0x00	; 0
25
  12:	07 00       	\.word	0x0007	; \?\?\?\?
26
27
00000014 <__start2>:
28
  14:	68 94       	set
29
30
00000016 <__vec2_start>:
31
  16:	e1 e0       	ldi	r30, 0x01	; 1
32
  18:	f0 91 00 00 	lds	r31, 0x0000	; 0x800000 <__data6\+0x7fff42>
33
  1c:	f0 93 00 00 	sts	0x0000, r31	; 0x800000 <__data6\+0x7fff42>
34
  20:	12 01       	movw	r2, r4
35
  22:	12 95       	swap	r17
36
  24:	18 95       	reti
37
  26:	78 10       	cpse	r7, r8
38
  28:	78 94       	sei
39
  2a:	f8 94       	cli
40
  2c:	af b6       	in	r10, 0x3f	; 63
41
  2e:	af be       	out	0x3f, r10	; 63
42
  30:	18 95       	reti
43
  32:	e8 94       	clt
44
45
00000034 <__data2>:
46
  34:	00 e0       	ldi	r16, 0x00	; 0
47
  36:	0f 00       	\.word	0x000f	; \?\?\?\?
48
49
00000038 <__start3>:
50
  38:	68 94       	set
51
52
0000003a <__vec3_start>:
53
  3a:	1f 92       	push	r1
54
  3c:	1f b6       	in	r1, 0x3f	; 63
55
  3e:	1f 92       	push	r1
56
  40:	11 24       	eor	r1, r1
57
  42:	8f 93       	push	r24
58
  44:	8f 91       	pop	r24
59
  46:	1f 90       	pop	r1
60
  48:	1f be       	out	0x3f, r1	; 63
61
  4a:	1f 90       	pop	r1
62
  4c:	18 95       	reti
63
  4e:	8f 91       	pop	r24
64
  50:	1f 90       	pop	r1
65
  52:	1f be       	out	0x3f, r1	; 63
66
  54:	1f 90       	pop	r1
67
  56:	18 95       	reti
68
  58:	13 94       	inc	r1
69
  5a:	e8 94       	clt
70
71
0000005c <__data3>:
72
  5c:	00 e0       	ldi	r16, 0x00	; 0
73
  5e:	11 00       	\.word	0x0011	; \?\?\?\?
74
75
00000060 <__start4>:
76
  60:	68 94       	set
77
78
00000062 <__vec4_start>:
79
  62:	0f 92       	push	r0
80
  64:	0f b6       	in	r0, 0x3f	; 63
81
  66:	0f 92       	push	r0
82
  68:	1f 92       	push	r1
83
  6a:	11 24       	eor	r1, r1
84
  6c:	8f 93       	push	r24
85
  6e:	8f 91       	pop	r24
86
  70:	1f 90       	pop	r1
87
  72:	0f 90       	pop	r0
88
  74:	0f be       	out	0x3f, r0	; 63
89
  76:	0f 90       	pop	r0
90
  78:	18 95       	reti
91
  7a:	8f 91       	pop	r24
92
  7c:	1f 90       	pop	r1
93
  7e:	0f 90       	pop	r0
94
  80:	0f be       	out	0x3f, r0	; 63
95
  82:	0f 90       	pop	r0
96
  84:	18 95       	reti
97
  86:	01 9f       	mul	r16, r17
98
  88:	e8 94       	clt
99
100
0000008a <__data4>:
101
  8a:	00 e0       	ldi	r16, 0x00	; 0
102
  8c:	14 00       	\.word	0x0014	; \?\?\?\?
103
104
0000008e <__start5>:
105
  8e:	68 94       	set
106
107
00000090 <__vec5_start>:
108
  90:	0f 92       	push	r0
109
  92:	c8 95       	lpm
110
  94:	0f 90       	pop	r0
111
  96:	18 95       	reti
112
  98:	0f 90       	pop	r0
113
  9a:	18 95       	reti
114
  9c:	e8 94       	clt
115
116
0000009e <__data5>:
117
  9e:	00 e0       	ldi	r16, 0x00	; 0
118
  a0:	07 00       	\.word	0x0007	; \?\?\?\?
119
120
000000a2 <__start6>:
121
  a2:	68 94       	set
122
123
000000a4 <__vec6_start>:
124
  a4:	af 93       	push	r26
125
  a6:	af b7       	in	r26, 0x3f	; 63
126
  a8:	af 93       	push	r26
127
  aa:	af 91       	pop	r26
128
  ac:	af bf       	out	0x3f, r26	; 63
129
  ae:	af 91       	pop	r26
130
  b0:	18 95       	reti
131
  b2:	af 91       	pop	r26
132
  b4:	af bf       	out	0x3f, r26	; 63
133
  b6:	af 91       	pop	r26
134
  b8:	18 95       	reti
135
  ba:	88 94       	clc
136
  bc:	e8 94       	clt
137
138
000000be <__data6>:
139
  be:	00 e0       	ldi	r16, 0x00	; 0
140
  c0:	0d 00       	\.word	0x000d	; \?\?\?\?
(-)a/gas/testsuite/gas/avr/gccisr-01.s (+125 lines)
Line 0 Link Here
1
.text
2
3
;;; No epilogue:  Full prologue
4
5
__start1:
6
    set
7
8
__vec1_start:
9
    __gcc_isr 1
10
    foo = __gcc_isr.n_pushed
11
    __gcc_isr 0,r2
12
    clt
13
__vec1_end:
14
__data1:
15
    ldi r16, foo - 4
16
    .word (__vec1_end - __vec1_start) / 2
17
18
;;; Nothing used.
19
20
__start2:
21
    set
22
23
__vec2_start:
24
    __gcc_isr 1
25
    foo = __gcc_isr.n_pushed
26
    ldi r30, 1
27
    lds r31, 0
28
    sts 0, r31
29
    movw r2, r4
30
    swap r17
31
    __gcc_isr 2
32
    reti
33
    __gcc_isr 2
34
    cpse r7, r8
35
    sei
36
    cli
37
    in  r10, 0x3f
38
    out 0x3f, r10
39
    reti
40
    __gcc_isr 0,r0
41
    clt
42
__vec2_end:
43
__data2:
44
    ldi r16, foo - 0
45
    .word (__vec2_end - __vec2_start) / 2
46
47
;;; Use SREG, ZERO and R24
48
49
__start3:
50
    set
51
52
__vec3_start:
53
    __gcc_isr 1
54
    foo = __gcc_isr.n_pushed
55
    __gcc_isr 2
56
    reti
57
    __gcc_isr 2
58
    reti
59
    inc r1
60
    __gcc_isr 0,r24
61
    clt
62
__vec3_end:
63
__data3:
64
    ldi r16, foo - 3
65
    .word (__vec3_end - __vec3_start) / 2
66
67
;;; Use SREG, ZERO, TMP and R24
68
69
__start4:
70
    set
71
72
__vec4_start:
73
    __gcc_isr 1
74
    foo = __gcc_isr.n_pushed
75
    __gcc_isr 2
76
    reti
77
    __gcc_isr 2
78
    reti
79
    mul 16, 17
80
    __gcc_isr 0,r24
81
    clt
82
__vec4_end:
83
__data4:
84
    ldi r16, foo - 4
85
    .word (__vec4_end - __vec4_start) / 2
86
87
;;; Use TMP
88
89
__start5:
90
    set
91
92
__vec5_start:
93
    __gcc_isr 1
94
    lpm
95
    foo = __gcc_isr.n_pushed
96
    __gcc_isr 2
97
    reti
98
    __gcc_isr 2
99
    reti
100
    __gcc_isr 0,r0
101
    clt
102
__vec5_end:
103
__data5:
104
    ldi r16, foo - 1
105
    .word (__vec5_end - __vec5_start) / 2
106
107
;;; Use SREG, R26
108
109
__start6:
110
    set
111
112
__vec6_start:
113
    __gcc_isr 1
114
    foo = __gcc_isr.n_pushed
115
    __gcc_isr 2
116
    reti
117
    __gcc_isr 2
118
    reti
119
    clc
120
    __gcc_isr 0,r26
121
    clt
122
__vec6_end:
123
__data6:
124
    ldi r16, foo - 2
125
    .word (__vec6_end - __vec6_start) / 2
(-)a/gas/testsuite/gas/avr/gccisr-02.d (+41 lines)
Line 0 Link Here
1
#name: gccisr-02: __gcc_isr pseudo instruction
2
#as: -mgcc-isr -mavrtiny
3
#objdump: -dz
4
#target: avr-*-*
5
6
.*: +file format elf32-avr
7
8
9
Disassembly of section \.text:
10
11
00000000 <__start1>:
12
   0:	68 94       	set
13
14
00000002 <__vec1_start>:
15
   2:	0f 93       	push	r16
16
   4:	0f b7       	in	r16, 0x3f	; 63
17
   6:	0f 93       	push	r16
18
   8:	1f 93       	push	r17
19
   a:	10 e0       	ldi	r17, 0x00	; 0
20
   c:	e8 94       	clt
21
22
0000000e <__data1>:
23
   e:	00 e0       	ldi	r16, 0x00	; 0
24
  10:	06 00       	\.word	0x0006	; \?\?\?\?
25
26
00000012 <__start2>:
27
  12:	68 94       	set
28
29
00000014 <__vec2_start>:
30
  14:	1f 93       	push	r17
31
  16:	10 e0       	ldi	r17, 0x00	; 0
32
  18:	1f 91       	pop	r17
33
  1a:	18 95       	reti
34
  1c:	e1 2f       	mov	r30, r17
35
  1e:	1f 91       	pop	r17
36
  20:	18 95       	reti
37
  22:	e8 94       	clt
38
39
00000024 <__data2>:
40
  24:	00 e0       	ldi	r16, 0x00	; 0
41
  26:	08 00       	\.word	0x0008	; \?\?\?\?
(-)a/gas/testsuite/gas/avr/gccisr-02.s (+36 lines)
Line 0 Link Here
1
.text
2
3
;;; No epilogue: Full prologue
4
5
__start1:
6
    set
7
8
__vec1_start:
9
    __gcc_isr 1
10
    foo = __gcc_isr.n_pushed
11
    __gcc_isr 0,r16
12
    clt
13
__vec1_end:
14
__data1:
15
    ldi r16, foo - 3
16
    .word (__vec1_end - __vec1_start) / 2
17
18
;;; Use ZERO
19
20
__start2:
21
    set
22
23
__vec2_start:
24
    __gcc_isr 1
25
    foo = __gcc_isr.n_pushed
26
    __gcc_isr 2
27
    reti
28
    mov r30,r17
29
    __gcc_isr 2
30
    reti
31
    __gcc_isr 0,r16
32
    clt
33
__vec2_end:
34
__data2:
35
    ldi r16, foo - 1
36
    .word (__vec2_end - __vec2_start) / 2
(-)a/gas/testsuite/gas/avr/gccisr-03.d (+4 lines)
Line 0 Link Here
1
#name: __gcc_isr pseudo instruction, test gccisr-03
2
#as: 
3
#error: pseudo instruction `__gcc_isr' not supported
4
#target: avr-*-*
(-)a/gas/testsuite/gas/avr/gccisr-03.s (+6 lines)
Line 0 Link Here
1
.text
2
3
;;; 
4
5
__start1:
6
    __gcc_isr 1
(-)a/include/opcode/avr.h (+5 lines)
Lines 110-115 Link Here
110
   z - Z pointer register (for [e]lpm Rd,Z[+])
110
   z - Z pointer register (for [e]lpm Rd,Z[+])
111
   M - immediate value from 0 to 255
111
   M - immediate value from 0 to 255
112
   n - immediate value from 0 to 255 ( n = ~M ). Relocation impossible
112
   n - immediate value from 0 to 255 ( n = ~M ). Relocation impossible
113
   N - immediate value from 0 to 255. Relocation impossible
113
   s - immediate value from 0 to 7
114
   s - immediate value from 0 to 7
114
   P - Port address value from 0 to 63. (in, out)
115
   P - Port address value from 0 to 63. (in, out)
115
   p - Port address value from 0 to 31. (cbi, sbi, sbic, sbis)
116
   p - Port address value from 0 to 31. (cbi, sbi, sbic, sbis)
Lines 306-308 AVR_INSN (eijmp, "", "1001010000011001", 1, AVR_ISA_EIND, 0x9419) Link Here
306
/* DES instruction for encryption and decryption.  */
307
/* DES instruction for encryption and decryption.  */
307
AVR_INSN (des,  "E",   "10010100EEEE1011", 1, AVR_ISA_DES,  0x940B)
308
AVR_INSN (des,  "E",   "10010100EEEE1011", 1, AVR_ISA_DES,  0x940B)
308
309
310
/* Operands are evaluated by hand and won't pop new fux-ups.
311
   The pseudo-insn is hidden behind NOP so that avr-dis.c don't see it. */
312
AVR_INSN (__gcc_isr, "", "0000000000000000", 1, AVR_ISA_1200,  0x0)
313

Return to bug 21683