2017-01-15 10:51:37 +00:00
|
|
|
|
|
|
|
quad emit_ha(struct expr_t* expr, bool is_signed)
|
|
|
|
{
|
|
|
|
/* If this is a symbol reference, discard the symbol and keep only the
|
|
|
|
* offset part. */
|
|
|
|
quad type = expr->typ & S_TYP;
|
|
|
|
quad 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
quad emit_lo(struct expr_t* expr)
|
|
|
|
{
|
|
|
|
quad type = expr->typ & S_TYP;
|
|
|
|
quad 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;
|
|
|
|
}
|