From f34a1764652499fbfe06f88d3ac3e92307816385 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 31 Jan 2017 11:35:57 -0500 Subject: [PATCH] In PowerPC as, refactor the hi16/ha16/lo16 code. This defers the call to newrelo() until we know the instruction. In the future, I might be able to check the instruction's opcode against the opcodes known to our linker led. --- mach/powerpc/as/mach1.c | 5 +-- mach/powerpc/as/mach4.c | 41 +++++++++++----------- mach/powerpc/as/mach5.c | 76 ++++++++++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 50 deletions(-) diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 44b415ff8..50f799684 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -7,5 +7,6 @@ * Do not #include anything here. Do it in mach/proto/as/comm0.h */ -extern word_t emit_hi(struct expr_t* expr, int is_signed); -extern word_t emit_lo(struct expr_t* expr); +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 640573fa1..8a0cca9de 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -10,11 +10,11 @@ operation | OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } | OP_BF_FRA_FRB CR ',' FPR ',' FPR { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); } | OP_BF_L_RA_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); } - | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } - | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } | OP_BF_RA_RB cr_opt GPR ',' GPR { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); } - | OP_BF_RA_SI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } - | OP_BF_RA_UI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_SI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_UI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } | OP_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); } | OP_BH { emit4($1); } | OP_BH u2 { emit4($1 | ($2<<11)); } @@ -33,13 +33,13 @@ operation | OP_BT_BT_BT u5 { emit4($1 | ($2<<21) | ($2<<16) | ($2<<11)); } | OP_BT_C c u5 { emit4($1 | $2 | ($3<<21)); } | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } - | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } - | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } | OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } @@ -59,34 +59,34 @@ operation { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } - | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } + | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit_hl($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit_hl($1 | ($5<<21) | ($3<<16) | $7); } | OP_RT GPR { emit4($1 | ($2<<21)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } - | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } - | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } + | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | OP_RT_RA_SI_subi GPR ',' GPR ',' negate16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI_subic c GPR ',' GPR ',' negate16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | OP_RT_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); } - | OP_RT_SI GPR ',' e16 { emit4($1 | ($2<<21) | $4); } + | OP_RT_SI GPR ',' e16 { emit_hl($1 | ($2<<21) | $4); } | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } - | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } | OP_TOX_RA_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); } - | OP_TOX_RA_SI GPR ',' e16 { emit4($1 | ($2<<16) | $4); } + | OP_TOX_RA_SI GPR ',' e16 { emit_hl($1 | ($2<<16) | $4); } | OP_LEV { emit4($1); } | OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LIA lia { emit4($1 | $2); } @@ -217,10 +217,11 @@ e16 if (($1 < -0x8000) || ($1 > 0xffff)) serror("16-bit value out of range"); $$ = (uint16_t) $1; + no_hl(); } - | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 0); } - | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 1); } - | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HI); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HA); } + | OP_LO ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_LO); } ; negate16 diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 47460790c..222508d21 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,38 +1,58 @@ +static int hl_token; +static expr_t hl_expr; -word_t emit_hi(struct expr_t* expr, int is_signed) +void no_hl(void) { + hl_token = 0; +} + +word_t eval_hl(expr_t* expr, int token) { - /* If this is a symbol reference, discard the symbol and keep only the - * offset part. */ - word_t type = expr->typ & S_TYP; word_t val = expr->val; uint16_t hi = val >> 16; uint16_t lo = val & 0xffff; - if (type != S_ABS) - newrelo(expr->typ, RELOPPC | FIXUPFLAGS); - - /* If the low half of this relocation is going to be a memory operation, - * then it'll be treated as a signed value. That means that values greater - * than 0x7fff will cause the high word to have 1 subtracted from it; so - * we apply an adjustment here. - */ - - if (is_signed && (lo > 0x7fff)) - hi++; - - return hi; + hl_token = token; + hl_expr = *expr; + + switch (token) { + case OP_HI: + /* hi16[expr] */ + return hi; + case OP_HA: + /* ha16[expr]: If the low half will be treated as a signed + * value, then values greater than 0x7fff will cause the high + * half to have 1 subtracted from it; so we apply an + * adjustment here. + */ + if (lo > 0x7fff) + hi++; + return hi; + case OP_LO: + /* lo16[expr] */ + return lo; + } } -word_t emit_lo(struct expr_t* expr) +void emit_hl(word_t in) { - word_t type = expr->typ & S_TYP; - word_t val = expr->val; - - /* If the assembler stored a symbol for relocation later, we need to - * abandon it (because the relocation was generated by emit_ha). */ - - if (type != S_ABS) - relonami = 0; - - return val & 0xffff; + int type; + + switch (hl_token) { + case OP_HI: + case OP_HA: + type = hl_expr.typ & S_TYP; + if (type != S_ABS) + newrelo(hl_expr.typ, RELOPPC | FIXUPFLAGS); + break; + case OP_LO: + /* If the assembler stored a symbol for relocation later, we + * need to abandon it (because the relocation was generated by + * hi16 or ha16). */ + type = hl_expr.typ & S_TYP; + if (type != S_ABS) + relonami = 0; + break; + } + + emit4(in); } -- 2.34.1