From 532b34d34fde93b2841f4c9544c673a0d89434ea Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 5 Apr 2025 15:53:10 -0700 Subject: Fix vs0 bugs Use a BoolNode.NE instead of inverting outputs; the outputs are already matched and cannot be inverted. Use a `swap` not an `invert` when switching sides in a compare. --- .../src/main/java/com/seaofnodes/simple/node/BoolNode.java | 12 ++++++++++++ .../src/main/java/com/seaofnodes/simple/node/IfNode.java | 14 ++++++++++++++ .../com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java | 2 +- .../seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java | 5 +++-- .../seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java | 10 +++++----- 5 files changed, 35 insertions(+), 8 deletions(-) (limited to 'chapter21/src/main/java') diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/BoolNode.java index f5f6a1de..fd6448a2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -92,6 +92,18 @@ abstract public class BoolNode extends Node { Node copyF() { return new EQF(null,null); } } + public static class NE extends BoolNode { + public NE(Node lhs, Node rhs) { super(lhs,rhs); } + public String op() { return "!="; } + TypeInteger doOp(TypeInteger i1, TypeInteger i2) { + if( i1==i2 && i1.isConstant() ) return TRUE; + if( i1._max < i2._min || i1._min > i2._max ) return FALSE; + return BOOL; + } + Node copy(Node lhs, Node rhs) { return new NE(lhs,rhs); } + Node copyF() { throw Utils.TODO(); } + } + public static class LT extends BoolNode { public LT(Node lhs, Node rhs) { super(lhs,rhs); } public String op() { return "<" ; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/IfNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/IfNode.java index c65e9a3b..f00f4f9f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/IfNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/IfNode.java @@ -69,6 +69,7 @@ public class IfNode extends CFGNode implements MultiNode { // The following CProjs will be inverted by the caller. public void invert() { throw Utils.TODO(); } + // Negate the sense of a test public static String invert( String bop ) { return switch( bop ) { case "<" -> ">="; @@ -80,4 +81,17 @@ public class IfNode extends CFGNode implements MultiNode { default -> throw Utils.TODO(); }; } + + // Swap compare operands + public static String swap( String bop ) { + return switch( bop ) { + case "<" -> ">" ; + case "<=" -> ">="; + case "==" -> "!="; + case "!=" -> "=="; + case ">" -> "<" ; + case ">=" -> "<="; + default -> throw Utils.TODO(); + }; + } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java index 36e32bb8..b684b4c4 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SetX86.java @@ -30,7 +30,7 @@ public class SetX86 extends MachConcreteNode implements MachNode { enc.add1(switch (_bop) { case "==" -> 0x94; // SETE case "<" -> 0x9C; // SETL - case "<=" -> 0X9E; // SETLE + case "<=" -> 0x96; //0X9E; // SETLE default -> throw Utils.TODO(); }); enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, 0, dst)); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java index f474b431..073d1d9b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java @@ -77,13 +77,14 @@ public class SplitX86 extends SplitNode { enc.add1(0x0F); enc.add1(0x28); } else if( dstX && !srcX ) { - // xmm->reg (66 REX.W 0F 6E /r MOVQ xmm, r/m64) + // reg->xmm (66 REX.W 0F 6E /r MOVQ xmm, r/m64) enc.add1(0x0F); enc.add1(0x6E); } else if( !dstX && srcX ) { - // reg->xmm(66 REX.W 0F 7E /r MOVQ r/m64, xmm) + // xmm->reg(66 0F 7E /r MOVQ r/m64, xmm) enc.add1(0x0F); enc.add1(0x7E); + short tmp=src; src=dst; dst=tmp; } enc.add1(x86_64_v2.modrm(x86_64_v2.MOD.DIRECT, dst, src)); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index bf8f92ad..98b14a3c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -502,11 +502,11 @@ public class x86_64_v2 extends Machine { // Because X86 flags, a normal ideal Bool is 2 X86 ops: a "cmp" and at "setz". // Ideal If reading from a setz will skip it and use the "cmp" instead. - private static boolean invert; + private static boolean swap; private Node cmp( BoolNode bool ) { - invert = false; + swap = false; Node cmp = _cmp(bool); - return new SetX86(cmp, invert ? IfNode.invert(bool.op()) : bool.op()); + return new SetX86(cmp, swap ? IfNode.swap(bool.op()) : bool.op()); } private Node _cmp(BoolNode bool) { @@ -528,7 +528,7 @@ public class x86_64_v2 extends Machine { return new CmpIX86(bool, (int)ti.value()); if( lhs instanceof ConstantNode con && con._con instanceof TypeInteger ti && imm32(ti.value()) ) { - invert = true; + swap = true; return new CmpIX86(bool, (int)ti.value(), 0.5); } @@ -560,7 +560,7 @@ public class x86_64_v2 extends Machine { // Loads do not set the flags, and will need an explicit TEST BoolNode bool; if( iff.in(1) instanceof BoolNode bool0 ) bool = bool0; - else iff.setDef(1, bool=new BoolNode.EQ(iff.in(1), new ConstantNode(TypeInteger.ZERO))); + else iff.setDef(1, bool=new BoolNode.NE(iff.in(1), new ConstantNode(TypeInteger.ZERO))); return new JmpX86(iff, bool.op()); } -- cgit v1.2.3