* ldlex.l (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): New tokens.
[deliverable/binutils-gdb.git] / ld / ldexp.c
index ec449fd8d5f2298456e524206e9a9bc5f530bda7..4023639a56b2b1a4c3c67a37550832ba5ec58a34 100644 (file)
@@ -64,6 +64,8 @@ static etree_value_type exp_fold_tree_no_dot
           lang_output_section_statement_type *current_section,
           lang_phase_type allocation_done));
 
+struct exp_data_seg exp_data_seg;
+
 static void
 exp_print_token (code)
      token_code_type code;
@@ -114,6 +116,8 @@ exp_print_token (code)
     { LOADADDR, "LOADADDR" },
     { MAX_K, "MAX_K" },
     { REL, "relocateable" },
+    { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
+    { DATA_SEGMENT_END, "DATA_SEGMENT_END" }
   };
   unsigned int idx;
 
@@ -314,6 +318,33 @@ fold_binary (tree, current_section, allocation_done, dot, dotp)
                result = other;
              break;
 
+           case DATA_SEGMENT_ALIGN:
+             if (allocation_done != lang_first_phase_enum
+                 && current_section == abs_output_section
+                 && (exp_data_seg.phase == exp_dataseg_none
+                     || exp_data_seg.phase == exp_dataseg_adjust
+                     || allocation_done != lang_allocating_phase_enum))
+               {
+                 bfd_vma maxpage = result.value;
+
+                 result.value = ALIGN_N (dot, maxpage);
+                 if (exp_data_seg.phase != exp_dataseg_adjust)
+                   {
+                     result.value += dot & (maxpage - 1);
+                     if (allocation_done == lang_allocating_phase_enum)
+                       {
+                         exp_data_seg.phase = exp_dataseg_align_seen;
+                         exp_data_seg.base = result.value;
+                         exp_data_seg.pagesize = other.value;
+                       }
+                   }
+                 else if (other.value < maxpage)
+                   result.value += dot & (maxpage - other.value);
+               }
+             else
+               result.valid_p = false;
+             break;
+
            default:
              FAIL ();
            }
@@ -578,6 +609,23 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
                result.valid_p = false;
              break;
 
+           case DATA_SEGMENT_END:
+             if (allocation_done != lang_first_phase_enum
+                 && current_section == abs_output_section
+                 && (exp_data_seg.phase == exp_dataseg_align_seen
+                     || exp_data_seg.phase == exp_dataseg_adjust
+                     || allocation_done != lang_allocating_phase_enum))
+               {
+                 if (exp_data_seg.phase == exp_dataseg_align_seen)
+                   {
+                     exp_data_seg.phase = exp_dataseg_end_seen;
+                     exp_data_seg.end = result.value;
+                   }
+               }
+             else
+               result.valid_p = false;
+             break;
+
            default:
              FAIL ();
              break;
@@ -615,7 +663,7 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
            {
              result = exp_fold_tree (tree->assign.src,
                                      current_section,
-                                     lang_allocating_phase_enum, dot,
+                                     allocation_done, dot,
                                      dotp);
              if (! result.valid_p)
                einfo (_("%F%S invalid assignment to location counter\n"));
This page took 0.023695 seconds and 4 git commands to generate.