@@ -6,13 +6,14 @@ use super::{
66} ;
77
88use crate :: masm:: {
9- DivKind , ExtendKind , FloatCmpKind , Imm as I , IntCmpKind , MacroAssembler as Masm , OperandSize ,
10- RegImm , RemKind , RoundingMode , ShiftKind , TrapCode , TruncKind , TRUSTED_FLAGS , UNTRUSTED_FLAGS ,
9+ DivKind , ExtendKind , FloatCmpKind , Imm as I , IntCmpKind , MacroAssembler as Masm , MulWideKind ,
10+ OperandSize , RegImm , RemKind , RoundingMode , ShiftKind , TrapCode , TruncKind , TRUSTED_FLAGS ,
11+ UNTRUSTED_FLAGS ,
1112} ;
1213use crate :: {
1314 abi:: { self , align_to, calculate_frame_adjustment, LocalSlot } ,
1415 codegen:: { ptr_type_from_ptr_size, CodeGenContext , FuncEnv } ,
15- stack:: Val ,
16+ stack:: { TypedReg , Val } ,
1617} ;
1718use crate :: {
1819 abi:: { vmctx, ABI } ,
@@ -996,6 +997,68 @@ impl Masm for MacroAssembler {
996997 fn current_code_offset ( & self ) -> CodeOffset {
997998 self . asm . buffer ( ) . cur_offset ( )
998999 }
1000+
1001+ fn add128 (
1002+ & mut self ,
1003+ dst_lo : WritableReg ,
1004+ dst_hi : WritableReg ,
1005+ lhs_lo : Reg ,
1006+ lhs_hi : Reg ,
1007+ rhs_lo : Reg ,
1008+ rhs_hi : Reg ,
1009+ ) {
1010+ Self :: ensure_two_argument_form ( & dst_lo. to_reg ( ) , & lhs_lo) ;
1011+ Self :: ensure_two_argument_form ( & dst_hi. to_reg ( ) , & lhs_hi) ;
1012+ self . asm . add_rr ( rhs_lo, dst_lo, OperandSize :: S64 ) ;
1013+ self . asm . adc_rr ( rhs_hi, dst_hi, OperandSize :: S64 ) ;
1014+ }
1015+
1016+ fn sub128 (
1017+ & mut self ,
1018+ dst_lo : WritableReg ,
1019+ dst_hi : WritableReg ,
1020+ lhs_lo : Reg ,
1021+ lhs_hi : Reg ,
1022+ rhs_lo : Reg ,
1023+ rhs_hi : Reg ,
1024+ ) {
1025+ Self :: ensure_two_argument_form ( & dst_lo. to_reg ( ) , & lhs_lo) ;
1026+ Self :: ensure_two_argument_form ( & dst_hi. to_reg ( ) , & lhs_hi) ;
1027+ self . asm . sub_rr ( rhs_lo, dst_lo, OperandSize :: S64 ) ;
1028+ self . asm . sbb_rr ( rhs_hi, dst_hi, OperandSize :: S64 ) ;
1029+ }
1030+
1031+ fn mul_wide ( & mut self , context : & mut CodeGenContext , kind : MulWideKind ) {
1032+ // Reserve rax/rdx since they're required by the `mul_wide` instruction
1033+ // being used here.
1034+ let rax = context. reg ( regs:: rax ( ) , self ) ;
1035+ let rdx = context. reg ( regs:: rdx ( ) , self ) ;
1036+
1037+ // The rhs of this binop can be in any register
1038+ let rhs = context. pop_to_reg ( self , None ) ;
1039+ // Mark rax as allocatable. and then force the lhs operand to be placed
1040+ // in `rax`.
1041+ context. free_reg ( rax) ;
1042+ let lhs = context. pop_to_reg ( self , Some ( rax) ) ;
1043+
1044+ self . asm . mul_wide (
1045+ writable ! ( rax) ,
1046+ writable ! ( rdx) ,
1047+ lhs. reg ,
1048+ rhs. reg ,
1049+ kind,
1050+ OperandSize :: S64 ,
1051+ ) ;
1052+
1053+ // No longer using the rhs register after the multiplication has been
1054+ // executed.
1055+ context. free_reg ( rhs) ;
1056+
1057+ // The low bits of the result are in rax, where `lhs` was allocated to
1058+ context. stack . push ( lhs. into ( ) ) ;
1059+ // The high bits of the result are in rdx, which we previously reserved.
1060+ context. stack . push ( Val :: Reg ( TypedReg :: i64 ( rdx) ) ) ;
1061+ }
9991062}
10001063
10011064impl MacroAssembler {
0 commit comments