[codegen] add intcc conditions for reading overflow flag

Add conditions to IntCC for checking the overflow flag (Overflow,
NotOverflow).
This commit is contained in:
Ujjwal Sharma
2019-09-07 17:34:38 +05:30
committed by Benjamin Bouvier
parent dfdd504edc
commit 43a891dfa2
7 changed files with 34 additions and 45 deletions

View File

@@ -2920,21 +2920,9 @@ pub(crate) fn define<'shared>(
{{PUT_OP}}(bits, rex2(in_reg0, in_reg1), sink); {{PUT_OP}}(bits, rex2(in_reg0, in_reg1), sink);
modrm_rr(in_reg0, in_reg1, sink); modrm_rr(in_reg0, in_reg1, sink);
// `setCC` instruction, no REX. // `setCC` instruction, no REX.
use crate::ir::condcodes::IntCC::*; let setcc = 0x90 | icc2opc(cond);
let setcc = match cond {
Equal => 0x94,
NotEqual => 0x95,
SignedLessThan => 0x9c,
SignedGreaterThanOrEqual => 0x9d,
SignedGreaterThan => 0x9f,
SignedLessThanOrEqual => 0x9e,
UnsignedLessThan => 0x92,
UnsignedGreaterThanOrEqual => 0x93,
UnsignedGreaterThan => 0x97,
UnsignedLessThanOrEqual => 0x96,
};
sink.put1(0x0f); sink.put1(0x0f);
sink.put1(setcc); sink.put1(setcc as u8);
modrm_rr(out_reg0, 0, sink); modrm_rr(out_reg0, 0, sink);
"#, "#,
), ),
@@ -2971,21 +2959,9 @@ pub(crate) fn define<'shared>(
let imm: i64 = imm.into(); let imm: i64 = imm.into();
sink.put1(imm as u8); sink.put1(imm as u8);
// `setCC` instruction, no REX. // `setCC` instruction, no REX.
use crate::ir::condcodes::IntCC::*; let setcc = 0x90 | icc2opc(cond);
let setcc = match cond {
Equal => 0x94,
NotEqual => 0x95,
SignedLessThan => 0x9c,
SignedGreaterThanOrEqual => 0x9d,
SignedGreaterThan => 0x9f,
SignedLessThanOrEqual => 0x9e,
UnsignedLessThan => 0x92,
UnsignedGreaterThanOrEqual => 0x93,
UnsignedGreaterThan => 0x97,
UnsignedLessThanOrEqual => 0x96,
};
sink.put1(0x0f); sink.put1(0x0f);
sink.put1(setcc); sink.put1(setcc as u8);
modrm_rr(out_reg0, 0, sink); modrm_rr(out_reg0, 0, sink);
"#, "#,
), ),
@@ -3006,21 +2982,9 @@ pub(crate) fn define<'shared>(
let imm: i64 = imm.into(); let imm: i64 = imm.into();
sink.put4(imm as u32); sink.put4(imm as u32);
// `setCC` instruction, no REX. // `setCC` instruction, no REX.
use crate::ir::condcodes::IntCC::*; let setcc = 0x90 | icc2opc(cond);
let setcc = match cond {
Equal => 0x94,
NotEqual => 0x95,
SignedLessThan => 0x9c,
SignedGreaterThanOrEqual => 0x9d,
SignedGreaterThan => 0x9f,
SignedLessThanOrEqual => 0x9e,
UnsignedLessThan => 0x92,
UnsignedGreaterThanOrEqual => 0x93,
UnsignedGreaterThan => 0x97,
UnsignedLessThanOrEqual => 0x96,
};
sink.put1(0x0f); sink.put1(0x0f);
sink.put1(setcc); sink.put1(setcc as u8);
modrm_rr(out_reg0, 0, sink); modrm_rr(out_reg0, 0, sink);
"#, "#,
), ),

View File

@@ -129,6 +129,8 @@ impl Immediates {
intcc_values.insert("ugt", "UnsignedGreaterThan"); intcc_values.insert("ugt", "UnsignedGreaterThan");
intcc_values.insert("ule", "UnsignedLessThanOrEqual"); intcc_values.insert("ule", "UnsignedLessThanOrEqual");
intcc_values.insert("ult", "UnsignedLessThan"); intcc_values.insert("ult", "UnsignedLessThan");
intcc_values.insert("of", "Overflow");
intcc_values.insert("nof", "NotOverflow");
Builder::new_enum("intcc", intcc_values) Builder::new_enum("intcc", intcc_values)
.doc("An integer comparison condition code.") .doc("An integer comparison condition code.")
.default_member("cond") .default_member("cond")

View File

@@ -1587,6 +1587,7 @@ pub(crate) fn define(
let y = &operand("y", Int); let y = &operand("y", Int);
// TODO(ryzokuken): Add documentation for unsigned overflow. // TODO(ryzokuken): Add documentation for unsigned overflow.
// TODO(ryzokuken): Add documentation for signed overflow.
ig.push( ig.push(
Inst::new( Inst::new(
"icmp", "icmp",

View File

@@ -51,6 +51,10 @@ pub enum IntCC {
UnsignedGreaterThan, UnsignedGreaterThan,
/// Unsigned `<=`. /// Unsigned `<=`.
UnsignedLessThanOrEqual, UnsignedLessThanOrEqual,
/// Signed Overflow.
Overflow,
/// Signed No Overflow.
NotOverflow,
} }
impl CondCode for IntCC { impl CondCode for IntCC {
@@ -67,6 +71,8 @@ impl CondCode for IntCC {
UnsignedGreaterThanOrEqual => UnsignedLessThan, UnsignedGreaterThanOrEqual => UnsignedLessThan,
UnsignedGreaterThan => UnsignedLessThanOrEqual, UnsignedGreaterThan => UnsignedLessThanOrEqual,
UnsignedLessThanOrEqual => UnsignedGreaterThan, UnsignedLessThanOrEqual => UnsignedGreaterThan,
Overflow => NotOverflow,
NotOverflow => Overflow,
} }
} }
@@ -83,6 +89,8 @@ impl CondCode for IntCC {
UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual, UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual,
UnsignedLessThan => UnsignedGreaterThan, UnsignedLessThan => UnsignedGreaterThan,
UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual, UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual,
Overflow => Overflow,
NotOverflow => NotOverflow,
} }
} }
} }
@@ -101,6 +109,8 @@ impl Display for IntCC {
UnsignedGreaterThanOrEqual => "uge", UnsignedGreaterThanOrEqual => "uge",
UnsignedLessThan => "ult", UnsignedLessThan => "ult",
UnsignedLessThanOrEqual => "ule", UnsignedLessThanOrEqual => "ule",
Overflow => "of",
NotOverflow => "nof",
}) })
} }
} }
@@ -121,6 +131,8 @@ impl FromStr for IntCC {
"ugt" => Ok(UnsignedGreaterThan), "ugt" => Ok(UnsignedGreaterThan),
"ule" => Ok(UnsignedLessThanOrEqual), "ule" => Ok(UnsignedLessThanOrEqual),
"ult" => Ok(UnsignedLessThan), "ult" => Ok(UnsignedLessThan),
"of" => Ok(Overflow),
"nof" => Ok(NotOverflow),
_ => Err(()), _ => Err(()),
} }
} }
@@ -270,7 +282,7 @@ mod tests {
use super::*; use super::*;
use std::string::ToString; use std::string::ToString;
static INT_ALL: [IntCC; 10] = [ static INT_ALL: [IntCC; 12] = [
IntCC::Equal, IntCC::Equal,
IntCC::NotEqual, IntCC::NotEqual,
IntCC::SignedLessThan, IntCC::SignedLessThan,
@@ -281,6 +293,8 @@ mod tests {
IntCC::UnsignedGreaterThanOrEqual, IntCC::UnsignedGreaterThanOrEqual,
IntCC::UnsignedGreaterThan, IntCC::UnsignedGreaterThan,
IntCC::UnsignedLessThanOrEqual, IntCC::UnsignedLessThanOrEqual,
IntCC::Overflow,
IntCC::NotOverflow,
]; ];
#[test] #[test]

View File

@@ -272,8 +272,8 @@ fn sib<CS: CodeSink + ?Sized>(scale: u8, index: RegUnit, base: RegUnit, sink: &m
fn icc2opc(cond: IntCC) -> u16 { fn icc2opc(cond: IntCC) -> u16 {
use crate::ir::condcodes::IntCC::*; use crate::ir::condcodes::IntCC::*;
match cond { match cond {
// 0x0 = Overflow. Overflow => 0x0,
// 0x1 = !Overflow. NotOverflow => 0x1,
UnsignedLessThan => 0x2, UnsignedLessThan => 0x2,
UnsignedGreaterThanOrEqual => 0x3, UnsignedGreaterThanOrEqual => 0x3,
Equal => 0x4, Equal => 0x4,

View File

@@ -664,6 +664,10 @@ ebb11:
trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b
; asm: jnbe .+4; ud2 ; asm: jnbe .+4; ud2
trapif ule v11, user0 ; bin: 77 02 user0 0f 0b trapif ule v11, user0 ; bin: 77 02 user0 0f 0b
; asm: jo .+4; ud2
trapif of v11, user0 ; bin: 71 02 user0 0f 0b
; asm: jno .+4; ud2
trapif nof v11, user0 ; bin: 70 02 user0 0f 0b
; Stack check. ; Stack check.
; asm: cmpl %esp, %ecx ; asm: cmpl %esp, %ecx

View File

@@ -862,6 +862,10 @@ ebb11:
trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b trapif ugt v11, user0 ; bin: 76 02 user0 0f 0b
; asm: jnbe .+4; ud2 ; asm: jnbe .+4; ud2
trapif ule v11, user0 ; bin: 77 02 user0 0f 0b trapif ule v11, user0 ; bin: 77 02 user0 0f 0b
; asm: jo .+4; ud2
trapif of v11, user0 ; bin: 71 02 user0 0f 0b
; asm: jno .+4; ud2
trapif nof v11, user0 ; bin: 70 02 user0 0f 0b
; Debug trap. ; Debug trap.
debugtrap ; bin: cc debugtrap ; bin: cc