Turning bits on
orr Rd, Rs follows exactly the rules and does: two operands, destructive, and no immediate form. Setting bits with a constant therefore costs a mov to build the constant and then the orr itself, with the constant landing in the destination register.
0 mov r0, #48
2 orr r0, r1
4 bx lr
That is a function or-ing 0x30 onto its second argument, and it is the cheap case: nothing had to move out of the way.
When both operands are registers there is no constant to build and the whole thing collapses to one instruction:
0 orr r0, r1
2 bx lr
Which is worth keeping in mind while you read: a bare orr between two argument registers is the whole body, and every extra mov in the listing is a constant being made.
Now count constants. gcc 2.9 simplifies bitwise algebra before it picks instructions, and one of the rewrites it knows is merging two masks of the same value: (a & 3) | (a & 0x0C) becomes a single and with 15, one mov, one constant. Its repertoire is narrow — a constant meeting another constant through the same operator, and not much else — so in most listings every constant the author wrote survives as its own mov.
That makes the mov-built constants in front of you a fair count of the constants in the original C. Your target has two, and the order in which they are built tells you which operation ran first.
Your task
Write func_080d2f04 to reproduce the target assembly.