diff --git a/cranelift/docs/langref.rst b/cranelift/docs/langref.rst index 4001cf3688..d80554dc67 100644 --- a/cranelift/docs/langref.rst +++ b/cranelift/docs/langref.rst @@ -381,6 +381,7 @@ is zero. .. autoinst:: trapz .. autoinst:: trapnz .. autoinst:: trapif +.. autoinst:: trapff Function calls diff --git a/cranelift/filetests/isa/intel/binary32-float.cton b/cranelift/filetests/isa/intel/binary32-float.cton index 9b12506b80..8f60cf20be 100644 --- a/cranelift/filetests/isa/intel/binary32-float.cton +++ b/cranelift/filetests/isa/intel/binary32-float.cton @@ -470,6 +470,23 @@ ebb1: ; asm: jbe ebb1 brff ule v1, ebb1 ; bin: 76 f0 + ; asm: jp .+4; ud2 + trapff ord v1, user0 ; bin: 7a 02 0f 0b + ; asm: jnp .+4; ud2 + trapff uno v1, user0 ; bin: 7b 02 0f 0b + ; asm: je .+4; ud2 + trapff one v1, user0 ; bin: 74 02 0f 0b + ; asm: jne .+4; ud2 + trapff ueq v1, user0 ; bin: 75 02 0f 0b + ; asm: jna .+4; ud2 + trapff gt v1, user0 ; bin: 76 02 0f 0b + ; asm: jnae .+4; ud2 + trapff ge v1, user0 ; bin: 72 02 0f 0b + ; asm: jnb .+4; ud2 + trapff ult v1, user0 ; bin: 73 02 0f 0b + ; asm: jnbe .+4; ud2 + trapff ule v1, user0 ; bin: 77 02 0f 0b + ; asm: setnp %bl [-,%rbx] v10 = trueff ord v1 ; bin: 0f 9b c3 ; asm: setp %bl diff --git a/cranelift/filetests/isa/intel/binary64-float.cton b/cranelift/filetests/isa/intel/binary64-float.cton index 8ca4efd8d8..a6f47e53db 100644 --- a/cranelift/filetests/isa/intel/binary64-float.cton +++ b/cranelift/filetests/isa/intel/binary64-float.cton @@ -494,6 +494,23 @@ ebb1: ; asm: jbe ebb1 brff ule v1, ebb1 ; bin: 76 f0 + ; asm: jp .+4; ud2 + trapff ord v1, user0 ; bin: 7a 02 0f 0b + ; asm: jnp .+4; ud2 + trapff uno v1, user0 ; bin: 7b 02 0f 0b + ; asm: je .+4; ud2 + trapff one v1, user0 ; bin: 74 02 0f 0b + ; asm: jne .+4; ud2 + trapff ueq v1, user0 ; bin: 75 02 0f 0b + ; asm: jna .+4; ud2 + trapff gt v1, user0 ; bin: 76 02 0f 0b + ; asm: jnae .+4; ud2 + trapff ge v1, user0 ; bin: 72 02 0f 0b + ; asm: jnb .+4; ud2 + trapff ult v1, user0 ; bin: 73 02 0f 0b + ; asm: jnbe .+4; ud2 + trapff ule v1, user0 ; bin: 77 02 0f 0b + ; asm: setnp %bl [-,%rbx] v10 = trueff ord v1 ; bin: 0f 9b c3 ; asm: setp %bl diff --git a/cranelift/filetests/parser/tiny.cton b/cranelift/filetests/parser/tiny.cton index 748c8f9a13..b16dd058ab 100644 --- a/cranelift/filetests/parser/tiny.cton +++ b/cranelift/filetests/parser/tiny.cton @@ -216,6 +216,9 @@ ebb0(v0: i32): trapz v0, stk_ovf v1 = ifcmp_imm v0, 5 trapif ugt v1, oob + v2 = bitcast.f32 v1 + v3 = ffcmp v2, v2 + trapff uno v3, int_ovf return } ; sameln: function %cond_traps(i32) @@ -223,5 +226,8 @@ ebb0(v0: i32): ; nextln: trapz $v0, stk_ovf ; nextln: $v1 = ifcmp_imm v0, 5 ; nextln: trapif ugt $v1, oob +; nextln: $v2 = bitcast.f32 $v1 +; nextln: $v3 = ffcmp $v2, $v2 +; nextln: trapff uno $v3, int_ovf ; nextln: return ; nextln: } diff --git a/lib/cretonne/meta/base/formats.py b/lib/cretonne/meta/base/formats.py index 1be94a7b09..b50824581b 100644 --- a/lib/cretonne/meta/base/formats.py +++ b/lib/cretonne/meta/base/formats.py @@ -75,6 +75,7 @@ RegFill = InstructionFormat( Trap = InstructionFormat(trapcode) CondTrap = InstructionFormat(VALUE, trapcode) IntCondTrap = InstructionFormat(intcc, VALUE, trapcode) +FloatCondTrap = InstructionFormat(floatcc, VALUE, trapcode) # Finally extract the names of global variables in this module. InstructionFormat.extract_names(globals()) diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index 89fd36812d..7200e45e7d 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -176,6 +176,15 @@ trapif = Instruction( """, ins=(Cond, f, code), can_trap=True) +Cond = Operand('Cond', floatcc) +f = Operand('f', fflags) + +trapff = Instruction( + 'trapff', r""" + Trap when condition is true in floating point CPU flags. + """, + ins=(Cond, f, code), can_trap=True) + rvals = Operand('rvals', VARIABLE_ARGS, doc='return values') x_return = Instruction( diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 80614cb8b4..1f47a5da06 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -357,6 +357,8 @@ I64.enc(base.trap, *r.trap(0x0f, 0x0b)) # Using a standard EncRecipe, not the TailRecipe. I32.enc(base.trapif, r.trapif, 0) I64.enc(base.trapif, r.trapif, 0) +I32.enc(base.trapff, r.trapff, 0) +I64.enc(base.trapff, r.trapff, 0) # # Comparisons diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 9696a7ed43..965bc4331d 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -8,7 +8,7 @@ from cdsl.registers import RegClass from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry, NullAry from base.formats import Trap, Call, IndirectCall, Store, Load from base.formats import IntCompare, FloatCompare, IntCond, FloatCond -from base.formats import IntSelect, IntCondTrap +from base.formats import IntSelect, IntCondTrap, FloatCondTrap from base.formats import Jump, Branch, BranchInt, BranchFloat from base.formats import Ternary, FuncAddr, UnaryGlobalVar from base.formats import RegMove, RegSpill, RegFill, CopySpecial @@ -292,6 +292,20 @@ trapif = EncRecipe( sink.put1(0x0b); ''') +trapff = EncRecipe( + 'trapff', FloatCondTrap, size=4, ins=FLAG.eflags, outs=(), + clobbers_flags=False, + instp=floatccs(FloatCondTrap), + emit=''' + // Jump over a 2-byte ud2. + sink.put1(0x70 | (fcc2opc(cond.inverse()) as u8)); + sink.put1(2); + // ud2. + sink.put1(0x0f); + sink.put1(0x0b); + ''') + + # XX /r rr = TailRecipe( 'rr', Binary, size=1, ins=(GPR, GPR), outs=0, diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index 449da29b93..af570f7ad5 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -270,6 +270,12 @@ pub enum InstructionData { arg: Value, code: ir::TrapCode, }, + FloatCondTrap { + opcode: Opcode, + cond: FloatCC, + arg: Value, + code: ir::TrapCode, + }, } /// A variable list of `Value` operands used for function call arguments and passing arguments to diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index fa5c751430..a346573e67 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -366,6 +366,7 @@ impl<'a> Verifier<'a> { Trap { .. } | CondTrap { .. } | IntCondTrap { .. } | + FloatCondTrap { .. } | NullAry { .. } => {} } diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index ea9e3a3e4a..860550f666 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -429,6 +429,7 @@ pub fn write_operands( Trap { code, .. } => write!(w, " {}", code), CondTrap { arg, code, .. } => write!(w, " {}, {}", arg, code), IntCondTrap { cond, arg, code, .. } => write!(w, " {} {}, {}", cond, arg, code), + FloatCondTrap { cond, arg, code, .. } => write!(w, " {} {}, {}", cond, arg, code), } } diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index c4c7b6e852..6be56523df 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -2363,6 +2363,21 @@ impl<'a> Parser<'a> { code, } } + InstructionFormat::FloatCondTrap => { + let cond = self.match_enum("expected floatcc condition code")?; + let arg = self.match_value("expected SSA value operand")?; + self.match_token( + Token::Comma, + "expected ',' between operands", + )?; + let code = self.match_enum("expected trap code")?; + InstructionData::FloatCondTrap { + opcode, + cond, + arg, + code, + } + } }; Ok(idata) }