11//! S390x ISA: binary code emission.
22
33use crate :: binemit:: { Reloc , StackMap } ;
4- use crate :: ir:: condcodes:: IntCC ;
54use crate :: ir:: MemFlags ;
65use crate :: ir:: { SourceLoc , TrapCode } ;
76use crate :: isa:: s390x:: inst:: * ;
@@ -153,14 +152,9 @@ pub fn mem_emit(
153152 & enc_rxy ( opcode_rxy. unwrap ( ) , rd, base, index, disp. bits ( ) ) ,
154153 ) ;
155154 }
156- & MemArg :: Label { ref target } => {
157- if let Some ( l) = target. as_label ( ) {
158- sink. use_label_at_offset ( sink. cur_offset ( ) , l, LabelUse :: BranchRIL ) ;
159- }
160- put (
161- sink,
162- & enc_ril_b ( opcode_ril. unwrap ( ) , rd, target. as_ril_offset_or_zero ( ) ) ,
163- ) ;
155+ & MemArg :: Label { target } => {
156+ sink. use_label_at_offset ( sink. cur_offset ( ) , target, LabelUse :: BranchRIL ) ;
157+ put ( sink, & enc_ril_b ( opcode_ril. unwrap ( ) , rd, 0 ) ) ;
164158 }
165159 & MemArg :: Symbol {
166160 ref name, offset, ..
@@ -1904,60 +1898,43 @@ impl MachInstEmit for Inst {
19041898 & Inst :: EpiloguePlaceholder => {
19051899 // Noop; this is just a placeholder for epilogues.
19061900 }
1907- & Inst :: Jump { ref dest } => {
1901+ & Inst :: Jump { dest } => {
19081902 let off = sink. cur_offset ( ) ;
19091903 // Indicate that the jump uses a label, if so, so that a fixup can occur later.
1910- if let Some ( l) = dest. as_label ( ) {
1911- sink. use_label_at_offset ( off, l, LabelUse :: BranchRIL ) ;
1912- sink. add_uncond_branch ( off, off + 6 , l) ;
1913- }
1904+ sink. use_label_at_offset ( off, dest, LabelUse :: BranchRIL ) ;
1905+ sink. add_uncond_branch ( off, off + 6 , dest) ;
19141906 // Emit the jump itself.
19151907 let opcode = 0xc04 ; // BCRL
1916- put ( sink, & enc_ril_c ( opcode, 15 , dest . as_ril_offset_or_zero ( ) ) ) ;
1908+ put ( sink, & enc_ril_c ( opcode, 15 , 0 ) ) ;
19171909 }
19181910 & Inst :: IndirectBr { rn, .. } => {
19191911 let opcode = 0x07 ; // BCR
19201912 put ( sink, & enc_rr ( opcode, gpr ( 15 ) , rn) ) ;
19211913 }
19221914 & Inst :: CondBr {
1923- ref taken,
1924- ref not_taken,
1915+ taken,
1916+ not_taken,
19251917 cond,
19261918 } => {
19271919 let opcode = 0xc04 ; // BCRL
19281920
19291921 // Conditional part first.
19301922 let cond_off = sink. cur_offset ( ) ;
1931- if let Some ( l) = taken. as_label ( ) {
1932- sink. use_label_at_offset ( cond_off, l, LabelUse :: BranchRIL ) ;
1933- let inverted = & enc_ril_c ( opcode, cond. invert ( ) . bits ( ) , 0 ) ;
1934- sink. add_cond_branch ( cond_off, cond_off + 6 , l, inverted) ;
1935- }
1936- put (
1937- sink,
1938- & enc_ril_c ( opcode, cond. bits ( ) , taken. as_ril_offset_or_zero ( ) ) ,
1939- ) ;
1923+ sink. use_label_at_offset ( cond_off, taken, LabelUse :: BranchRIL ) ;
1924+ let inverted = & enc_ril_c ( opcode, cond. invert ( ) . bits ( ) , 0 ) ;
1925+ sink. add_cond_branch ( cond_off, cond_off + 6 , taken, inverted) ;
1926+ put ( sink, & enc_ril_c ( opcode, cond. bits ( ) , 0 ) ) ;
19401927
19411928 // Unconditional part next.
19421929 let uncond_off = sink. cur_offset ( ) ;
1943- if let Some ( l) = not_taken. as_label ( ) {
1944- sink. use_label_at_offset ( uncond_off, l, LabelUse :: BranchRIL ) ;
1945- sink. add_uncond_branch ( uncond_off, uncond_off + 6 , l) ;
1946- }
1947- put (
1948- sink,
1949- & enc_ril_c ( opcode, 15 , not_taken. as_ril_offset_or_zero ( ) ) ,
1950- ) ;
1930+ sink. use_label_at_offset ( uncond_off, not_taken, LabelUse :: BranchRIL ) ;
1931+ sink. add_uncond_branch ( uncond_off, uncond_off + 6 , not_taken) ;
1932+ put ( sink, & enc_ril_c ( opcode, 15 , 0 ) ) ;
19511933 }
1952- & Inst :: OneWayCondBr { ref target, cond } => {
1934+ & Inst :: OneWayCondBr { target, cond } => {
19531935 let opcode = 0xc04 ; // BCRL
1954- if let Some ( l) = target. as_label ( ) {
1955- sink. use_label_at_offset ( sink. cur_offset ( ) , l, LabelUse :: BranchRIL ) ;
1956- }
1957- put (
1958- sink,
1959- & enc_ril_c ( opcode, cond. bits ( ) , target. as_ril_offset_or_zero ( ) ) ,
1960- ) ;
1936+ sink. use_label_at_offset ( sink. cur_offset ( ) , target, LabelUse :: BranchRIL ) ;
1937+ put ( sink, & enc_ril_c ( opcode, cond. bits ( ) , 0 ) ) ;
19611938 }
19621939 & Inst :: Nop0 => { }
19631940 & Inst :: Nop2 => {
@@ -1984,86 +1961,49 @@ impl MachInstEmit for Inst {
19841961 let srcloc = state. cur_srcloc ( ) ;
19851962 put_with_trap ( sink, & enc_e ( 0x0000 ) , srcloc, trap_code) ;
19861963 }
1987- & Inst :: JTSequence {
1988- ridx,
1989- rtmp1,
1990- rtmp2,
1991- ref info,
1992- ..
1993- } => {
1964+ & Inst :: JTSequence { ridx, ref targets } => {
19941965 let table_label = sink. get_label ( ) ;
19951966
19961967 // This sequence is *one* instruction in the vcode, and is expanded only here at
19971968 // emission time, because we cannot allow the regalloc to insert spills/reloads in
19981969 // the middle; we depend on hardcoded PC-rel addressing below.
19991970
2000- // Bounds-check index and branch to default.
2001- let inst = Inst :: CmpRUImm32 {
2002- op : CmpOp :: CmpL64 ,
2003- rn : ridx,
2004- imm : info. targets . len ( ) as u32 ,
2005- } ;
2006- inst. emit ( sink, emit_info, state) ;
2007- let inst = Inst :: OneWayCondBr {
2008- target : info. default_target ,
2009- cond : Cond :: from_intcc ( IntCC :: UnsignedGreaterThanOrEqual ) ,
2010- } ;
2011- inst. emit ( sink, emit_info, state) ;
2012-
2013- // Set rtmp2 to index scaled by entry size.
2014- let inst = Inst :: ShiftRR {
2015- shift_op : ShiftOp :: LShL64 ,
2016- rd : rtmp2,
2017- rn : ridx,
2018- shift_imm : 2 ,
2019- shift_reg : zero_reg ( ) ,
2020- } ;
2021- inst. emit ( sink, emit_info, state) ;
2022-
2023- // Set rtmp1 to address of jump table.
1971+ // Set temp register to address of jump table.
1972+ let rtmp = writable_spilltmp_reg ( ) ;
20241973 let inst = Inst :: LoadAddr {
2025- rd : rtmp1 ,
1974+ rd : rtmp ,
20261975 mem : MemArg :: Label {
2027- target : BranchTarget :: Label ( table_label) ,
1976+ target : table_label,
20281977 } ,
20291978 } ;
20301979 inst. emit ( sink, emit_info, state) ;
20311980
2032- // Set rtmp2 to value loaded out of jump table.
2033- let inst = Inst :: Load64SExt32 {
2034- rd : rtmp2,
2035- mem : MemArg :: reg_plus_reg ( rtmp1. to_reg ( ) , rtmp2. to_reg ( ) , MemFlags :: trusted ( ) ) ,
2036- } ;
2037- inst. emit ( sink, emit_info, state) ;
2038-
2039- // Set rtmp1 to target address (rtmp1 + rtmp2).
2040- let inst = Inst :: AluRRR {
2041- alu_op : ALUOp :: Add64 ,
2042- rd : rtmp1,
2043- rn : rtmp1. to_reg ( ) ,
2044- rm : rtmp2. to_reg ( ) ,
1981+ // Set temp to target address by adding the value of the jump table entry.
1982+ let inst = Inst :: AluRX {
1983+ alu_op : ALUOp :: Add64Ext32 ,
1984+ rd : rtmp,
1985+ mem : MemArg :: reg_plus_reg ( rtmp. to_reg ( ) , ridx, MemFlags :: trusted ( ) ) ,
20451986 } ;
20461987 inst. emit ( sink, emit_info, state) ;
20471988
20481989 // Branch to computed address. (`targets` here is only used for successor queries
20491990 // and is not needed for emission.)
20501991 let inst = Inst :: IndirectBr {
2051- rn : rtmp1 . to_reg ( ) ,
1992+ rn : rtmp . to_reg ( ) ,
20521993 targets : vec ! [ ] ,
20531994 } ;
20541995 inst. emit ( sink, emit_info, state) ;
20551996
20561997 // Emit jump table (table of 32-bit offsets).
1998+ // The first entry is the default target, which is not emitted
1999+ // into the jump table, so we skip it here. It is only in the
2000+ // list so MachTerminator will see the potential target.
20572001 sink. bind_label ( table_label) ;
20582002 let jt_off = sink. cur_offset ( ) ;
2059- for & target in info . targets . iter ( ) {
2003+ for & target in targets. iter ( ) . skip ( 1 ) {
20602004 let word_off = sink. cur_offset ( ) ;
20612005 let off_into_table = word_off - jt_off;
2062- sink. use_label_at_offset (
2063- word_off,
2064- target. as_label ( ) . unwrap ( ) ,
2065- LabelUse :: PCRel32 ,
2066- ) ;
2006+ sink. use_label_at_offset ( word_off, target, LabelUse :: PCRel32 ) ;
20672007 sink. put4 ( off_into_table. swap_bytes ( ) ) ;
20682008 }
20692009
0 commit comments