- frag_var (rs_cfa, 4, 0, 0, make_expr_symbol (exp),
- d->loc4_fix, (char *) d->loc4_frag);
+ case state_saw_loc4:
+ d->state = state_wait_loc4;
+ if (*pnbytes != 4)
+ break;
+ if (exp->X_op == O_constant)
+ {
+ /* This is a case which we can optimize. The two symbols being
+ subtracted were in the same frag and the expression was
+ reduced to a constant. We can do the optimization entirely
+ in this function. */
+ if (d->cie_info.code_alignment > 0
+ && exp->X_add_number % d->cie_info.code_alignment == 0
+ && exp->X_add_number / d->cie_info.code_alignment < 0x40)
+ {
+ d->loc4_frag->fr_literal[d->loc4_fix]
+ = DW_CFA_advance_loc
+ | (exp->X_add_number / d->cie_info.code_alignment);
+ /* No more bytes needed. */
+ return 1;
+ }
+ else if (exp->X_add_number < 0x100)
+ {
+ d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
+ *pnbytes = 1;
+ }
+ else if (exp->X_add_number < 0x10000)
+ {
+ d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
+ *pnbytes = 2;
+ }
+ }
+ else if (exp->X_op == O_subtract)
+ {
+ /* This is a case we can optimize. The expression was not
+ reduced, so we can not finish the optimization until the end
+ of the assembly. We set up a variant frag which we handle
+ later. */
+ int fr_subtype;
+
+ if (d->cie_info.code_alignment > 0)
+ fr_subtype = d->cie_info.code_alignment << 3;
+ else
+ fr_subtype = 0;
+
+ frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp),
+ d->loc4_fix, (char *) d->loc4_frag);
+ return 1;
+ }
+ break;