// loadByType returns the load instruction of the given type. func loadByType(t ssa.Type, r int16) obj.As { if mips.REG_F0 <= r && r <= mips.REG_F31 { if t.IsFloat() && t.Size() == 4 { // float32 return mips.AMOVF } else { // float64 or integer in FP register return mips.AMOVD } } else { switch t.Size() { case 1: if t.IsSigned() { return mips.AMOVB } else { return mips.AMOVBU } case 2: if t.IsSigned() { return mips.AMOVH } else { return mips.AMOVHU } case 4: if t.IsSigned() { return mips.AMOVW } else { return mips.AMOVWU } case 8: return mips.AMOVV } } panic("bad load type") }
// moveByType returns the reg->reg move instruction of the given type. func moveByType(t ssa.Type) obj.As { if t.IsFloat() { // Moving the whole sse2 register is faster // than moving just the correct low portion of it. // There is no xmm->xmm move with 1 byte opcode, // so use movups, which has 2 byte opcode. return x86.AMOVUPS } else { switch t.Size() { case 1: // Avoids partial register write return x86.AMOVL case 2: return x86.AMOVL case 4: return x86.AMOVL case 8: return x86.AMOVQ case 16: return x86.AMOVUPS // int128s are in SSE registers default: panic(fmt.Sprintf("bad int register width %d:%s", t.Size(), t)) } } panic("bad register type") }
// loadByType returns the load instruction of the given type. func loadByType(t ssa.Type) obj.As { if t.IsFloat() { switch t.Size() { case 4: return arm.AMOVF case 8: return arm.AMOVD } } else { switch t.Size() { case 1: if t.IsSigned() { return arm.AMOVB } else { return arm.AMOVBU } case 2: if t.IsSigned() { return arm.AMOVH } else { return arm.AMOVHU } case 4: return arm.AMOVW } } panic("bad load type") }
// loadByType returns the load instruction of the given type. func loadByType(t ssa.Type, r int16) obj.As { if isFPreg(r) { if t.Size() == 4 { // float32 or int32 return mips.AMOVF } else { // float64 or int64 return mips.AMOVD } } else { switch t.Size() { case 1: if t.IsSigned() { return mips.AMOVB } else { return mips.AMOVBU } case 2: if t.IsSigned() { return mips.AMOVH } else { return mips.AMOVHU } case 4: return mips.AMOVW } } panic("bad load type") }
// loadByType returns the load instruction of the given type. func loadByType(t ssa.Type) obj.As { if t.IsFloat() { switch t.Size() { case 4: return s390x.AFMOVS case 8: return s390x.AFMOVD } } else { switch t.Size() { case 1: if t.IsSigned() { return s390x.AMOVB } else { return s390x.AMOVBZ } case 2: if t.IsSigned() { return s390x.AMOVH } else { return s390x.AMOVHZ } case 4: if t.IsSigned() { return s390x.AMOVW } else { return s390x.AMOVWZ } case 8: return s390x.AMOVD } } panic("bad load type") }
// loadByType returns the load instruction of the given type. func loadByType(t ssa.Type) obj.As { // Avoid partial register write if !t.IsFloat() && t.Size() <= 2 { if t.Size() == 1 { return x86.AMOVBLZX } else { return x86.AMOVWLZX } } // Otherwise, there's no difference between load and store opcodes. return storeByType(t) }
// storeByType returns the store instruction of the given type. func storeByType(t ssa.Type, r int16) obj.As { if isFPreg(r) { if t.Size() == 4 { // float32 or int32 return mips.AMOVF } else { // float64 or int64 return mips.AMOVD } } else { switch t.Size() { case 1: return mips.AMOVB case 2: return mips.AMOVH case 4: return mips.AMOVW } } panic("bad store type") }
// storeByType returns the store instruction of the given type. func storeByType(t ssa.Type) obj.As { if t.IsFloat() { switch t.Size() { case 4: return arm.AMOVF case 8: return arm.AMOVD } } else { switch t.Size() { case 1: return arm.AMOVB case 2: return arm.AMOVH case 4: return arm.AMOVW } } panic("bad store type") }
// storeByType returns the store instruction of the given type. func storeByType(t ssa.Type) obj.As { width := t.Size() if t.IsFloat() { switch width { case 4: return x86.AMOVSS case 8: return x86.AMOVSD } } else { switch width { case 1: return x86.AMOVB case 2: return x86.AMOVW case 4: return x86.AMOVL } } panic("bad store type") }
// storeByType returns the store instruction of the given type. func storeByType(t ssa.Type, r int16) obj.As { if mips.REG_F0 <= r && r <= mips.REG_F31 { if t.IsFloat() && t.Size() == 4 { // float32 return mips.AMOVF } else { // float64 or integer in FP register return mips.AMOVD } } else { switch t.Size() { case 1: return mips.AMOVB case 2: return mips.AMOVH case 4: return mips.AMOVW case 8: return mips.AMOVV } } panic("bad store type") }
// moveByType returns the reg->reg move instruction of the given type. func moveByType(t ssa.Type) obj.As { if t.IsFloat() { switch t.Size() { case 4: return x86.AMOVSS case 8: return x86.AMOVSD default: panic(fmt.Sprintf("bad float register width %d:%s", t.Size(), t)) } } else { switch t.Size() { case 1: // Avoids partial register write return x86.AMOVL case 2: return x86.AMOVL case 4: return x86.AMOVL default: panic(fmt.Sprintf("bad int register width %d:%s", t.Size(), t)) } } }
// loadPush returns the opcode for load+push of the given type. func loadPush(t ssa.Type) obj.As { if t.Size() == 4 { return x86.AFMOVF } return x86.AFMOVD }