From e947ce7a7fbdf554ebcde07649dadbcbdcd50690 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 6 Feb 2017 13:19:01 -0500 Subject: [PATCH] Fix two problems with previous commit. 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 | 3 +- mach/powerpc/as/mach1.c | 1 + mach/powerpc/as/mach4.c | 9 ++++-- mach/powerpc/as/mach5.c | 61 ++++++++++++++++++++++++++--------------- mach/proto/as/comm0.h | 1 + mach/proto/as/comm7.c | 2 ++ 6 files changed, 51 insertions(+), 26 deletions(-) diff --git a/mach/powerpc/as/mach0.c b/mach/powerpc/as/mach0.c index 4e2e4ebe2..48659b5c5 100644 --- a/mach/powerpc/as/mach0.c +++ b/mach/powerpc/as/mach0.c @@ -26,7 +26,8 @@ #define ALIGNSECT 4 #undef machfinish -/* machfinish() in mach5.c */ +#undef machload +/* defined in mach5.c */ #undef VALWIDTH #define VALWIDTH 8 diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 10e7a2b5f..1efc288d1 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -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); diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 8a0cca9de..10b27f829 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -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); } } ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 88e028c10..446c8019c 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -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)) { diff --git a/mach/proto/as/comm0.h b/mach/proto/as/comm0.h index 2d00c8e45..06eee8dfb 100644 --- a/mach/proto/as/comm0.h +++ b/mach/proto/as/comm0.h @@ -70,6 +70,7 @@ _include #define machstart(x) /* nothing */ #define machfinish(x) /* nothing */ +#define machload(x) /* nothing */ #define SETBASE(sp) ((long)(sp)->s_base) diff --git a/mach/proto/as/comm7.c b/mach/proto/as/comm7.c index 3c7871fbe..6eb7da268 100644 --- a/mach/proto/as/comm7.c +++ b/mach/proto/as/comm7.c @@ -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) -- 2.34.1