word_t emit_hi(struct expr_t* expr, int is_signed) { /* 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; } word_t emit_lo(struct expr_t* expr) { 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; }