[codegen] add intcc conditions for reading overflow flag
Add conditions to IntCC for checking the overflow flag (Overflow, NotOverflow).
This commit is contained in:
committed by
Benjamin Bouvier
parent
dfdd504edc
commit
43a891dfa2
@@ -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);
|
||||||
"#,
|
"#,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user