Ling-hua Tseng wrote:It's obvious that `movil' and `movim' are only access the partial 16-bit of the 32-bit register. How can I use RTL expression to represent the operations?
As you noticed, within a register, subreg can only be used for low parts. You can't ask for the high part of a single register. If you have an item that spans multiple registers, e.g. a 64-bit value that is contained in a register pair, then you can ask for the SImode highpart of a DImode reg and get valid RTL. This works because the high part is an entire register. This isn't useful to you.
Otherwise, you can access subparts via bitfield insert/extract operations, or logicals operations (ior/and), though this is likely to be tedious, and may confuse optimizers.
There are high/lo_sum RTL operators that may be useful to you. You can use (set (reg:SI) (high: ...)) (set (reg:SI) (lo_sum (reg:SI) (...))) where the first pattern corresponds to movims, and the second one to movil. You could just as well use ior instead of lo_sum for the second pattern, this is probably better as movil does not do an add.
You may want to emit normal rtl for an SImode move, and then split it into its two 16-bit parts after reload. This will avoid confusing RTL optimizers before reload.
We have vector modes which might be useful to you. If you say a register is holding a V4QI mode value, then there are natural ways to get at the individual elements of the vector via vector operations.
I implemented my 4 `movi' cases in the following forms. The result of them sould be a 32-bit integer because the `movi' is in order to generate SImode immediate. The case 4 is special. It's also used to generate HImode and QImode immediates. Would you like to help me confirm them? (RTX semantics and the usage of `HI' mode)
1. set MSB 16-bit and clear LSB 16-bit to zero [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand:SI 1 "immediate_operand" "i")))] (Does (high:SI ...) have the semantic of clearing LSB 16-bit ? )
2. set MSB 16-bit and unchange/keep LSB 16-bit [(parallel [(set (high:SI (match_operand:SI 0 "register_operand" "=r")) (high:SI (match_operand:SI 1 "immediate_operand" "i"))) (set (strict_lowpart (subreg:HI (match_dup 0) 0)) (match_operand:HI "immediate_operand" "i"))])] (I know it's incorrect if the semantic of (high:SI ...) will change LSB 16-bit.)
3. set LSB 16-bit and clear MSB 16-bit to zero [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:HI 1 "immediate_operand" "i"))]
4. set LSB 16-bit and unchange/keep LSB 16-bit [(set (strict_lowpart (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)) (match_operand:HI "immediate_operand" "i"))] (Would it better than use (lo_sum:SI ...) ? )
Thanks.