Fix two problems with previous commit.
authorGeorge Koehler <xkernigh@netscape.net>
Mon, 6 Feb 2017 18:19:01 +0000 (13:19 -0500)
committerGeorge Koehler <xkernigh@netscape.net>
Mon, 6 Feb 2017 18:19:01 +0000 (13:19 -0500)
First, I can't use relonami to compare symbols, because relonami
doesn't have different values for different symbols until pass 3.  I
was wrongly pairing a hi16 or ha16 with a different symbol's lo16.
Fix by comparing item pointers.  Hack mach/proto/as/comm7.c to pass
each item pointer to mach/proto/as/mach5.c

Second, I broke hi16[...] and ha16[...] for absolute values.  Fix by
checking hr_head with DOTVAL and DOTTYP.

Having fixed the second problem, I can now switch li32 to use
eval_hl() and emit_hl(), without breaking programs that li32 an
absolute value.

mach/powerpc/as/mach0.c
mach/powerpc/as/mach1.c
mach/powerpc/as/mach4.c
mach/powerpc/as/mach5.c
mach/proto/as/comm0.h
mach/proto/as/comm7.c

index 4e2e4eb..48659b5 100644 (file)
@@ -26,7 +26,8 @@
 #define ALIGNSECT      4
 
 #undef machfinish
-/* machfinish() in mach5.c */
+#undef machload
+/* defined in mach5.c */
 
 #undef VALWIDTH
 #define VALWIDTH       8
index 10e7a2b..1efc288 100644 (file)
@@ -7,6 +7,7 @@
  * Do not #include anything here.  Do it in mach/proto/as/comm0.h
  */
 
+void machload(item_t* item);
 void no_hl(void);
 word_t eval_hl(struct expr_t* expr, int token);
 void emit_hl(word_t in);
index 8a0cca9..10b27f8 100644 (file)
@@ -374,9 +374,12 @@ li32
                        emit4((14<<26) | ($1<<21) | (0<<16)  | val); /* addi */
                else
                {
-                       newrelo($3.typ, RELOPPC | FIXUPFLAGS);
-                       emit4((15<<26) | ($1<<21) | (0<<16)  | (val >> 16)); /* addis */
-                       emit4((24<<26) | ($1<<21) | ($1<<16) | (val & 0xffff)); /* ori */
+                       /* addis, ori */
+                       word_t hi, lo;
+                       hi = eval_hl(&$3, OP_HI);
+                       emit_hl((15<<26) | ($1<<21) | (0<<16)  | hi);
+                       lo = eval_hl(&$3, OP_LO);
+                       emit_hl((24<<26) | ($1<<21) | ($1<<16) | lo);
                }
        }
        ;
index 88e028c..446c801 100644 (file)
@@ -5,21 +5,24 @@
  * certain specific opcodes.
  */
 
+static item_t *last_und_item;
+
 /* Info about the current hi16, ha16, or lo16 */
 static int hl_token;
 static expr_t hl_expr;
+static item_t* hl_item;             /* undefined symbol or NULL */
 
 /* Info about each hi16 or ha16 relocation */
 struct hirel {
+    expr_t          hr_expr;
     struct hirel*   hr_next;        /* next hirel in source order */
     struct hirel*   hr_inext;       /* next incomplete hirel */
-    expr_t          hr_expr;
-    valu_t          hr_relonami;
-    short           hr_token;       /* OP_HI or OP_HA */
-    short           hr_dottyp;      /* section */
+    item_t*         hr_item;        /* undefined symbol or NULL */
+    long            hr_lineno;
     ADDR_T          hr_hidot;       /* address of hi16/ha16 */
     ADDR_T          hr_lodot;       /* address of matching lo16 */
-    long            hr_lineno;
+    short           hr_dottyp;      /* section */
+    short           hr_token;       /* OP_HI or OP_HA */
 };
 static struct hirel* hr_head = NULL;
 static struct hirel* hr_tail = NULL;
@@ -31,6 +34,18 @@ static int lo_count2 = 0;           /* pass 2 */
 static int lo_count3 = 0;           /* pass 3 */
 
 
+static int is_und(int typ)
+{
+    return (typ & S_TYP) == S_UND || typ & S_COM;
+}
+
+void machload(item_t* item)
+{
+    if (is_und(item->i_type)) {
+        last_und_item = item;
+    }
+}
+
 void no_hl(void) {
     hl_token = 0;
 }
@@ -44,6 +59,10 @@ word_t eval_hl(expr_t* expr, int token)
 
     hl_token = token;
     hl_expr = *expr;
+    if (is_und(expr->typ))
+        hl_item = last_und_item;
+    else
+        hl_item = NULL;
 
     switch (token) {
     case OP_HA:  /* ha16[expr] */
@@ -59,16 +78,15 @@ word_t eval_hl(expr_t* expr, int token)
         if (pass == PASS_3) {
             /* Get the hirel from emit_hl() PASS_2. */
             hr = hr_head;
-            if (DOTVAL != hr->hr_hidot)
-                abort();
-
-            /* For now, the lo16 must be in the next instruction. */
-            if (DOTVAL + 4 != hr->hr_lodot)
-                serror("%s needs lo16 in next instruction",
-                       token == OP_HI ? "hi16" : "ha16");
+            if (hr && hr->hr_hidot == DOTVAL && hr->hr_dottyp == DOTTYP) {
+                /* For now, the lo16 must be in the next instruction. */
+                if (DOTVAL + 4 != hr->hr_lodot)
+                    serror("%s needs lo16 in next instruction",
+                           token == OP_HI ? "hi16" : "ha16");
 
-            hr_head = hr->hr_next;
-            free(hr);
+                hr_head = hr->hr_next;
+                free(hr);
+            }
         }
         return hi;
     case OP_LO:  /* lo16[expr] */
@@ -90,7 +108,7 @@ static int hr_match(const struct hirel* hr, int und)
      */
     return (hr->hr_expr.typ == hl_expr.typ &&
             hr->hr_expr.val == hl_expr.val &&
-            (!und || hr->hr_relonami == relonami) &&
+            (!und || hr->hr_item == hl_item) &&
             hr->hr_dottyp == DOTTYP);
 }
 
@@ -124,15 +142,15 @@ void emit_hl(word_t in)
                 hr = malloc(sizeof(*hr));
                 if (!hr)
                     fatal("out of memory");
+                hr->hr_expr = hl_expr;
                 hr->hr_next = NULL;
                 hr->hr_inext = hr_ihead;
-                hr->hr_expr = hl_expr;
-                hr->hr_relonami = relonami;
-                hr->hr_token = hl_token;
-                hr->hr_dottyp = DOTTYP;
+                hr->hr_item = hl_item;
+                hr->hr_lineno = lineno;
                 hr->hr_hidot = DOTVAL;
                 hr->hr_lodot = 0;
-                hr->hr_lineno = lineno;
+                hr->hr_dottyp = DOTTYP;
+                hr->hr_token = hl_token;
 
                 /* Add it to end of main list. */
                 if (hr_tail) {
@@ -152,8 +170,7 @@ void emit_hl(word_t in)
             switch (pass) {
             case PASS_2:
                 /* Search for hi16 or ha16 to complete. */
-                und = ((hl_expr.typ & S_TYP) == S_UND ||
-                       (hl_expr.typ & S_COM));
+                und = is_und(hl_expr.typ);
                 hrlink = &hr_ihead;
                 while (hr = *hrlink) {
                     if (hr_match(hr, und)) {
index 2d00c8e..06eee8d 100644 (file)
@@ -70,6 +70,7 @@ _include      <string.h>
 
 #define        machstart(x)    /* nothing */
 #define        machfinish(x)   /* nothing */
+#define machload(x)     /* nothing */
 
 #define        SETBASE(sp)     ((long)(sp)->s_base)
 
index 3c7871f..6eb7da2 100644 (file)
@@ -20,11 +20,13 @@ register item_t *ip;
 #ifdef ASLD
        register typ;
 
+       machload(ip);
        typ = ip->i_type & S_TYP;
        if ((typ -= S_MIN) < 0)         /* S_UND or S_ABS */
                return(ip->i_valu);
        return(ip->i_valu + sect[typ].s_base);
 #else
+       machload(ip);
        if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) {
                if (pass == PASS_3) {
                        if (relonami != 0)