diff options
Diffstat (limited to 'isa')
5 files changed, 49 insertions, 0 deletions
diff --git a/isa/src/main/java/com/seaofnodes/isa/Arm64.java b/isa/src/main/java/com/seaofnodes/isa/Arm64.java index ce7f7b11..5edb2f3c 100644 --- a/isa/src/main/java/com/seaofnodes/isa/Arm64.java +++ b/isa/src/main/java/com/seaofnodes/isa/Arm64.java @@ -4,6 +4,12 @@ package com.seaofnodes.isa; public final class Arm64 { private Arm64() {} + // MRS Xt,NZCV / MSR NZCV,Xt. Register 31 denotes XZR. + public static int flags(int reg, boolean toFlags) { + assert 0<=reg && reg<32; + return (toFlags ? 0xD51B4200 : 0xD53B4200) | reg; + } + public static final int OP_ADD = 0b10_001_011; public static final int OPF_ADD = 0b00_011_110; public static final int OPF_OP_ADD = 0b00_101_0; diff --git a/isa/src/main/java/com/seaofnodes/isa/X86.java b/isa/src/main/java/com/seaofnodes/isa/X86.java index 78fa3da5..d5150a31 100644 --- a/isa/src/main/java/com/seaofnodes/isa/X86.java +++ b/isa/src/main/java/com/seaofnodes/isa/X86.java @@ -162,11 +162,18 @@ public final class X86 { } } public static void flags(CodeSink out, int reg, boolean toFlags) { + assert 0<=reg && reg<16 && reg!=4; if( !toFlags ) out.add1(0x9C); // PUSHF rexF(0,reg,-1,false,out); out.add1((toFlags ? 0x50 : 0x58)+(reg&7)); if( toFlags ) out.add1(0x9D); // POPF } + public static void flagsStack(CodeSink out, int offset, boolean toFlags) { + if( !toFlags ) out.add1(0x9C); // PUSHFQ + // POP's destination uses the restored RSP, so offset needs no adjustment. + memory(out,0,toFlags ? 0xFF : 0x8F,false,toFlags ? 6 : 0,4,-1,offset,0); + if( toFlags ) out.add1(0x9D); // POPFQ + } public static void stackCopy(CodeSink out, int srcOffset, int dstOffset) { memory(out,0,0xFF,false,6,4,-1,srcOffset,0); // PUSH [rsp+srcOffset] memory(out,0,0x8F,false,0,4,-1,dstOffset,0); // POP uses the restored rsp. diff --git a/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java index 1ff77f59..d4a54719 100644 --- a/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java +++ b/isa/src/test-support/java/com/seaofnodes/isa/eval/EvalArm64.java @@ -597,6 +597,22 @@ public class EvalArm64 { break; } + case 0xD5: { + if( (ir & ~31)==0xD53B4200 ) { // MRS Xt,NZCV + rval = (N ? 1L<<31 : 0) | (Z ? 1L<<30 : 0) | + (C ? 1L<<29 : 0) | (V ? 1L<<28 : 0); + if( rdid==31 ) rdid=-1; // XZR, not SP. + } else if( (ir & ~31)==0xD51B4200 ) { // MSR NZCV,Xt + long value = rdid==31 ? 0 : regs[rdid]; + N = (value & (1L<<31))!=0; + Z = (value & (1L<<30))!=0; + C = (value & (1L<<29))!=0; + V = (value & (1L<<28))!=0; + rdid=-1; + } else throw new UnsupportedOperationException("Unknown system instruction"); + break; + } + case 0xD6: { int op = ir & 0xFFFFFC1F; int rn = (ir >>> 5) & 31; diff --git a/isa/src/test/java/com/seaofnodes/isa/RiscTest.java b/isa/src/test/java/com/seaofnodes/isa/RiscTest.java index d10f97a4..5b354036 100644 --- a/isa/src/test/java/com/seaofnodes/isa/RiscTest.java +++ b/isa/src/test/java/com/seaofnodes/isa/RiscTest.java @@ -9,6 +9,22 @@ public class RiscTest { assert expected==actual : String.format("Expected %08x, got %08x",expected,actual); } public static void main(String[] args) { + word(0xD53B4209,Arm64.flags(9,false)); // MRS x9,NZCV + word(0xD51B421A,Arm64.flags(26,true)); // MSR NZCV,x26 + for( int flags=0; flags<16; flags++ ) { + var a=new EvalArm64(new byte[1024],512); + a.st4(4,0xD51B4209); // MSR NZCV,x9 + a.st4(8,0xD53B421A); // MRS x26,NZCV + a.st4(12,0xD53B421F); // MRS xzr,NZCV + a.st4(16,0xD51B421F); // MSR NZCV,xzr + a._pc=4; a.regs[9]=((long)flags<<28) | 0xFFF; + assert a.step(3)==0; + assert a.regs[26]==(long)flags<<28 && a.regs[31]==512; + assert a.N==((flags&8)!=0) && a.Z==((flags&4)!=0); + assert a.C==((flags&2)!=0) && a.V==((flags&1)!=0); + assert a.step(1)==0; + assert !a.N && !a.Z && !a.C && !a.V && a.regs[31]==512; + } // Instructions encountered by dynamic allocation measurements. for( long[] pair : new long[][]{{17,3},{-17,3},{17,0},{Long.MIN_VALUE,-1}} ) { var a=new EvalArm64(new byte[1024],512); diff --git a/isa/src/test/java/com/seaofnodes/isa/X86Test.java b/isa/src/test/java/com/seaofnodes/isa/X86Test.java index 8af84ae8..4d3f1433 100644 --- a/isa/src/test/java/com/seaofnodes/isa/X86Test.java +++ b/isa/src/test/java/com/seaofnodes/isa/X86Test.java @@ -102,6 +102,10 @@ public class X86Test { check("41ffd2", b -> X86.callRegister(b,10)); check("41519d", b -> X86.flags(b,9,true)); check("9c4159", b -> X86.flags(b,9,false)); + check("9c8f442418", b -> X86.flagsStack(b,24,false)); + check("ff7424189d", b -> X86.flagsStack(b,24,true)); + check("9c8f842480000000", b -> X86.flagsStack(b,128,false)); + check("ffb424800000009d", b -> X86.flagsStack(b,128,true)); check("ff7424088f442410", b -> X86.stackCopy(b,8,16)); check("4d8bca", b -> X86.move(b,false,false,9,10)); check("4d0f28ca", b -> X86.move(b,true,true,9,10)); |
