summaryrefslogtreecommitdiff
path: root/chapter21/src/main
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-03-31 11:41:51 -0700
committerCliff Click <cliffc@acm.org>2025-03-31 11:41:51 -0700
commit760e2b4f57ceac91017ad018f2e9234af351bf5b (patch)
tree44b12ddd2f4a1116ec09ab3749f7f1d462718a2e /chapter21/src/main
parentd98a5c8cdf7a249f3c227fc00f014d53452af858 (diff)
downloadSimple-760e2b4f57ceac91017ad018f2e9234af351bf5b.tar.gz
Simple-760e2b4f57ceac91017ad018f2e9234af351bf5b.zip
X86 float splits
Diffstat (limited to 'chapter21/src/main')
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java26
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SplitX86.java16
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java35
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java2
-rw-r--r--chapter21/src/main/java/com/seaofnodes/simple/type/Type.java2
5 files changed, 45 insertions, 36 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
index 71085971..c857c0b1 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/LoadX86.java
@@ -23,29 +23,33 @@ public class LoadX86 extends MemOpX86 {
short dst = enc.reg(this );
short ptr = enc.reg(ptr());
short idx = enc.reg(idx());
+ enc(enc, _declaredType, dst, ptr, idx, _off, _scale);
+ }
- if( _declaredType != TypeInteger.U32 && _declaredType != TypeFloat.F32 && _declaredType != TypeFloat.F64 )
+ static void enc( Encoding enc, Type decl, short dst, short ptr, short idx, int off, int scale ) {
+ if( decl != TypeInteger.U32 && decl != TypeFloat.F32 && decl != TypeFloat.F64 )
enc.add1(x86_64_v2.rex(dst, ptr, idx));
- if( _declaredType.isa(TypeFloat.F64) )
+ if( decl.isa(TypeFloat.F64) )
dst -= (short)x86_64_v2.XMM_OFFSET;
if( false ) ;
- else if( _declaredType == TypeFloat.F32 ) enc.add1(0xF3).add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32
- else if( _declaredType == TypeFloat.F64 ) enc.add1(0xF2).add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64
- else if( _declaredType == TypeInteger.I8 ) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8
- else if( _declaredType == TypeInteger.I16) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16
- else if( _declaredType == TypeInteger.I32) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32
- else if( _declaredType == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8
- else if( _declaredType == TypeInteger.U16) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16
+ else if( decl == TypeFloat.F32 ) enc.add1(0xF3).add1(0x0F).add1(0x10); // F3 0F 10 /r MOVSS xmm1, m32
+ else if( decl == TypeFloat.F64 ) enc.add1(0xF2).add1(0x0F).add1(0x10); // F2 0F 10 /r MOVSD xmm1, m64
+ else if( decl == TypeInteger.I8 ) enc.add1(0x0F).add1(0xBE); // sign extend: REX.W + 0F BE /r MOVSX r64, r/m8
+ else if( decl == TypeInteger.I16) enc.add1(0x0F).add1(0xBF); // sign extend: REX.W + 0F BF /r MOVSX r64, r/m16
+ else if( decl == TypeInteger.I32) enc.add1(0x63); // sign extend: REX.W + 63 /r MOVSXD r64, r/m32
+ else if( decl == TypeInteger.U8 ) enc.add1(0x0F).add1(0xB6); // zero extend: REX.W + 0F B6 /r MOVZX r64, r/m8
+ else if( decl == TypeInteger.U16) enc.add1(0x0F).add1(0xB7); // zero extend: REX.W + 0F B7 /r MOVZX r64, r/m16
// Covers U32, I64/BOT, TMP
- else if( _declaredType.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32
+ else if( decl.log_size()>=2 ) enc.add1(0x8B); // zero extend: 8B /r MOV r32, r/m32
else throw Utils.TODO();
// includes modrm internally
- x86_64_v2.indirectAdr(_scale, idx, ptr, _off, dst, enc);
+ x86_64_v2.indirectAdr(scale, idx, ptr, off, dst, enc);
}
+
// General form: "ldN dst,[base + idx<<2 + 12]"
@Override public void asm(CodeGen code, SB sb) {
sb.p(code.reg(this)).p(",");
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 adf1e1a6..f474b431 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
@@ -5,6 +5,9 @@ import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.SplitNode;
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+import com.seaofnodes.simple.type.TypeInteger;
public class SplitX86 extends SplitNode {
SplitX86( String kind, byte round ) { super(kind,round, new Node[2]); }
@@ -23,6 +26,7 @@ public class SplitX86 extends SplitNode {
// push rcx
// popf (Pop the top of the stack into the FLAGS register)
// 50+rd PUSH r64
+ if( src >= 8 ) x86_64_v2.rex(0,src,0,true);
enc.add1(0x50 + src);
// popf
enc.add1(0x9D);
@@ -33,6 +37,7 @@ public class SplitX86 extends SplitNode {
// pushf; pop reg
enc.add1(0x9C);
// 58+ rd POP r64
+ if( dst >= 8 ) x86_64_v2.rex(0,dst,0,true);
enc.add1(0x58 + dst);
return;
}
@@ -45,20 +50,13 @@ public class SplitX86 extends SplitNode {
if( dst >= x86_64_v2.MAX_REG ) {
if( src >= x86_64_v2.MAX_REG )
throw Utils.TODO(); // Very rare stack-stack move
- // TODO: Missing FP 0x66 prefix
- if( srcX ) { src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0x66); }
int off = enc._fun.computeStackSlot(dst - x86_64_v2.MAX_REG)*8;
- enc.add1(x86_64_v2.rex(src, x86_64_v2.RSP, -1));
- enc.add1( 0x89 );
- x86_64_v2.indirectAdr(0, (short)-1, (short)x86_64_v2.RSP, off, src, enc);
+ StoreX86.encVal(enc, srcX ? TypeFloat.F64 : TypeInteger.BOT, (short)x86_64_v2.RSP, (short)-1/*index*/, src, off, 0);
return;
}
if( src >= x86_64_v2.MAX_REG ) {
- if( dstX ) { dst -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0x66); }
int off = enc._fun.computeStackSlot(src - x86_64_v2.MAX_REG)*8;
- enc.add1(x86_64_v2.rex(dst, x86_64_v2.RSP, -1));
- enc.add1( 0x8B );
- x86_64_v2.indirectAdr(0, (short)-1, (short)x86_64_v2.RSP, off, dst, enc);
+ LoadX86.enc(enc, dstX ? TypeFloat.F64 : TypeInteger.BOT, dst, (short)x86_64_v2.RSP, (short)-1, off, 0);
return;
}
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
index 52e4660d..6886a363 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/StoreX86.java
@@ -5,8 +5,8 @@ import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.ConstantNode;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.node.StoreNode;
+import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFloat;
-
import java.util.BitSet;
public class StoreX86 extends MemOpX86 {
@@ -30,31 +30,38 @@ public class StoreX86 extends MemOpX86 {
short idx = enc.reg(idx());
short src = enc.reg(val());
- if( src == -1 && _imm != 0 ) {
+ if( src == -1 ) {
// return opcode for optimised immediate store
if( x86_64_v2.imm8(_imm) ) enc.add1(0xC6);
else if( x86_64_v2.imm32(_imm) ) enc.add1(0xC7);
else enc.add1(x86_64_v2.rex(-1, ptr, idx)).add1(0xC7);
- } else {
- if(_declaredType == TypeFloat.F32) {src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0xF3); enc.add1(0x0F); enc.add1(0x11);}
- else if(_declaredType == TypeFloat.F64) {src -= (short)x86_64_v2.XMM_OFFSET; enc.add1(0xF2); enc.add1(0x0F); enc.add1(0x11);}
- else if(_declaredType.log_size() == 0) enc.add1(0x88);
- else if(_declaredType.log_size() == 1) enc.add1(0x89);
- else if(_declaredType.log_size() == 2) enc.add1(0x89);
- else if(_declaredType.log_size() == 3) {enc.add1(x86_64_v2.rex(src, ptr, idx)); enc.add1(0x89);}
- }
-
- x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc);
- if( src == -1 ) {
+ x86_64_v2.indirectAdr(_scale, idx, ptr, _off, src, enc);
switch (x86_64_v2.imm_size(_imm)) {
- case 8: enc.add1(_imm); break;
+ case 8: enc.add1(_imm); break;
case 16: enc.add2(_imm); break;
case 32: enc.add4(_imm); break;
case 64: enc.add8(_imm); break;
}
+ } else {
+ encVal(enc,_declaredType,ptr,idx,src,_off,_scale);
+ }
+ }
+
+ // Non-immediate encoding
+ static void encVal( Encoding enc, Type decl, short ptr, short idx, short src, int off, int scale ) {
+ if( decl instanceof TypeFloat ) {
+ src -= (short)x86_64_v2.XMM_OFFSET;
+ enc.add1( decl==TypeFloat.F32 ? 0xF3 : 0xF2 ).add1(0x0F).add1(0x11);
}
+ else if( decl.log_size() == 0 ) enc.add1(0x88);
+ else if( decl.log_size() == 1 ) enc.add1(0x89);
+ else if( decl.log_size() == 2 ) enc.add1(0x89);
+ else if( decl.log_size() == 3 ) enc.add1(x86_64_v2.rex(src, ptr, idx)).add1(0x89);
+
+ x86_64_v2.indirectAdr(scale, idx, ptr, off, src, enc);
}
+
// General form: "stN [base + idx<<2 + 12],val"
@Override public void asm(CodeGen code, SB sb) {
asm_address(code,sb).p(",");
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 69cb59aa..d475a260 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
@@ -165,7 +165,7 @@ public class x86_64_v2 extends Machine {
if( index == -1 ) {
// Case for mov reg, [disp] (load)
enc.add1(modrm(offset == 0 ? MOD.INDIRECT_disp8 : mod, reg, x86_64_v2.RSP));
- enc.add1(x86_64_v2.sib(scale, x86_64_v2.RSP, base));
+ enc.add1(sib(scale, x86_64_v2.RSP, base));
// special case
// still add zero it is part of SIB byte
if(offset == 0) enc.add1(offset);
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter21/src/main/java/com/seaofnodes/simple/type/Type.java
index 7dc091aa..6df4e7ab 100644
--- a/chapter21/src/main/java/com/seaofnodes/simple/type/Type.java
+++ b/chapter21/src/main/java/com/seaofnodes/simple/type/Type.java
@@ -218,7 +218,7 @@ public class Type {
// Sizes are expected to be between 1 and 64 bits.
// Size 0 means this either takes no space (such as a known-zero field)
// or isn't a scalar to be stored in memory.
- public int log_size() { throw Utils.TODO(); }
+ public int log_size() { return 3; }
// ----------------------------------------------------------
// Useful in the debugger, which calls toString everywhere.