@@ -11,17 +11,28 @@ use crate::trace;
1111use core:: convert:: TryFrom ;
1212use regalloc2:: Allocation ;
1313
14+ /// Type(s) of memory instructions available for mem_finalize.
15+ pub struct MemInstType {
16+ /// True if 12-bit unsigned displacement is supported.
17+ pub have_d12 : bool ,
18+ /// True if 20-bit signed displacement is supported.
19+ pub have_d20 : bool ,
20+ /// True if PC-relative addressing is supported (memory access).
21+ pub have_pcrel : bool ,
22+ /// True if PC-relative addressing is supported (load address).
23+ pub have_unaligned_pcrel : bool ,
24+ /// True if an index register is supported.
25+ pub have_index : bool ,
26+ }
27+
1428/// Memory addressing mode finalization: convert "special" modes (e.g.,
1529/// generic arbitrary stack offset) into real addressing modes, possibly by
1630/// emitting some helper instructions that come immediately before the use
1731/// of this amode.
1832pub fn mem_finalize (
1933 mem : & MemArg ,
2034 state : & EmitState ,
21- have_d12 : bool ,
22- have_d20 : bool ,
23- have_pcrel : bool ,
24- have_index : bool ,
35+ mi : MemInstType ,
2536) -> ( SmallVec < [ Inst ; 4 ] > , MemArg ) {
2637 let mut insts = SmallVec :: new ( ) ;
2738
@@ -70,9 +81,10 @@ pub fn mem_finalize(
7081
7182 // If this addressing mode cannot be handled by the instruction, use load-address.
7283 let need_load_address = match & mem {
73- & MemArg :: Label { .. } | & MemArg :: Symbol { .. } if !have_pcrel => true ,
74- & MemArg :: BXD20 { .. } if !have_d20 => true ,
75- & MemArg :: BXD12 { index, .. } | & MemArg :: BXD20 { index, .. } if !have_index => {
84+ & MemArg :: Label { .. } | & MemArg :: Symbol { .. } if !mi. have_pcrel => true ,
85+ & MemArg :: Symbol { flags, .. } if !mi. have_unaligned_pcrel && !flags. aligned ( ) => true ,
86+ & MemArg :: BXD20 { .. } if !mi. have_d20 => true ,
87+ & MemArg :: BXD12 { index, .. } | & MemArg :: BXD20 { index, .. } if !mi. have_index => {
7688 index != zero_reg ( )
7789 }
7890 _ => false ,
@@ -93,8 +105,8 @@ pub fn mem_finalize(
93105 index,
94106 disp,
95107 flags,
96- } if !have_d12 => {
97- assert ! ( have_d20) ;
108+ } if !mi . have_d12 => {
109+ assert ! ( mi . have_d20) ;
98110 MemArg :: BXD20 {
99111 base,
100112 index,
@@ -122,10 +134,13 @@ pub fn mem_emit(
122134 let ( mem_insts, mem) = mem_finalize (
123135 mem,
124136 state,
125- opcode_rx. is_some ( ) ,
126- opcode_rxy. is_some ( ) ,
127- opcode_ril. is_some ( ) ,
128- true ,
137+ MemInstType {
138+ have_d12 : opcode_rx. is_some ( ) ,
139+ have_d20 : opcode_rxy. is_some ( ) ,
140+ have_pcrel : opcode_ril. is_some ( ) ,
141+ have_unaligned_pcrel : opcode_ril. is_some ( ) && !add_trap,
142+ have_index : true ,
143+ } ,
129144 ) ;
130145 for inst in mem_insts. into_iter ( ) {
131146 inst. emit ( & [ ] , sink, emit_info, state) ;
@@ -190,10 +205,13 @@ pub fn mem_rs_emit(
190205 let ( mem_insts, mem) = mem_finalize (
191206 mem,
192207 state,
193- opcode_rs. is_some ( ) ,
194- opcode_rsy. is_some ( ) ,
195- false ,
196- false ,
208+ MemInstType {
209+ have_d12 : opcode_rs. is_some ( ) ,
210+ have_d20 : opcode_rsy. is_some ( ) ,
211+ have_pcrel : false ,
212+ have_unaligned_pcrel : false ,
213+ have_index : false ,
214+ } ,
197215 ) ;
198216 for inst in mem_insts. into_iter ( ) {
199217 inst. emit ( & [ ] , sink, emit_info, state) ;
@@ -236,7 +254,17 @@ pub fn mem_imm8_emit(
236254 emit_info : & EmitInfo ,
237255 state : & mut EmitState ,
238256) {
239- let ( mem_insts, mem) = mem_finalize ( mem, state, true , true , false , false ) ;
257+ let ( mem_insts, mem) = mem_finalize (
258+ mem,
259+ state,
260+ MemInstType {
261+ have_d12 : true ,
262+ have_d20 : true ,
263+ have_pcrel : false ,
264+ have_unaligned_pcrel : false ,
265+ have_index : false ,
266+ } ,
267+ ) ;
240268 for inst in mem_insts. into_iter ( ) {
241269 inst. emit ( & [ ] , sink, emit_info, state) ;
242270 }
@@ -274,7 +302,17 @@ pub fn mem_imm16_emit(
274302 emit_info : & EmitInfo ,
275303 state : & mut EmitState ,
276304) {
277- let ( mem_insts, mem) = mem_finalize ( mem, state, true , false , false , false ) ;
305+ let ( mem_insts, mem) = mem_finalize (
306+ mem,
307+ state,
308+ MemInstType {
309+ have_d12 : true ,
310+ have_d20 : false ,
311+ have_pcrel : false ,
312+ have_unaligned_pcrel : false ,
313+ have_index : false ,
314+ } ,
315+ ) ;
278316 for inst in mem_insts. into_iter ( ) {
279317 inst. emit ( & [ ] , sink, emit_info, state) ;
280318 }
@@ -336,7 +374,17 @@ pub fn mem_vrx_emit(
336374 emit_info : & EmitInfo ,
337375 state : & mut EmitState ,
338376) {
339- let ( mem_insts, mem) = mem_finalize ( mem, state, true , false , false , true ) ;
377+ let ( mem_insts, mem) = mem_finalize (
378+ mem,
379+ state,
380+ MemInstType {
381+ have_d12 : true ,
382+ have_d20 : false ,
383+ have_pcrel : false ,
384+ have_unaligned_pcrel : false ,
385+ have_index : true ,
386+ } ,
387+ ) ;
340388 for inst in mem_insts. into_iter ( ) {
341389 inst. emit ( & [ ] , sink, emit_info, state) ;
342390 }
0 commit comments