diff --git a/compiler/xtensa/cgcpu.pas b/compiler/xtensa/cgcpu.pas index 8a5cfb67a3..fa11abd09b 100644 --- a/compiler/xtensa/cgcpu.pas +++ b/compiler/xtensa/cgcpu.pas @@ -928,8 +928,95 @@ implementation procedure tcg64fxtensa.a_op64_const_reg_reg(list : TAsmList; op : TOpCG; size : tcgsize; value : int64; regsrc,regdst : tregister64); + var + tmpreg,tmplo,carry,tmphi,hreg: tregister; + tmpreg64 : tregister64; + b : byte; + signed : Boolean; + no_carry : TAsmLabel; + instr : taicpu; begin - list.Concat(taicpu.op_none(A_NOP)); + case op of + OP_NEG, + OP_NOT : + internalerror(2020030904); + else + ; + end; + case op of + OP_AND,OP_OR,OP_XOR: + begin + cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo); + cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi); + end; + OP_ADD: + begin + { could do better here (hi(value) in 248..2047), for now we support only the simple cases } + if (value>=-2048) and (value<=2047) then + begin + signed:=(size in [OS_S64]); + + tmplo := cg.GetIntRegister(list,OS_S32); + carry := cg.GetIntRegister(list,OS_S32); + + list.concat(taicpu.op_reg_reg_const(A_ADDI, tmplo, regsrc.reglo, value)); + if signed then + begin + list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regsrc.reghi, 0)); + + current_asmdata.getjumplabel(no_carry); + instr:=taicpu.op_reg_reg_sym(A_Bcc,tmplo, regsrc.reglo, no_carry); + instr.condition:=C_GEU; + list.concat(instr); + list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, regdst.reghi, 1)); + cg.a_label(list,no_carry); + end + else + begin + cg.a_load_const_reg(list,OS_INT,1,carry); + current_asmdata.getjumplabel(no_carry); + cg.a_cmp_reg_reg_label(list,OS_INT,OC_B,tmplo, regsrc.reglo,no_carry); + cg.a_load_const_reg(list,OS_INT,0,carry); + cg.a_label(list,no_carry); + + cg.a_load_reg_reg(list,OS_INT,OS_INT,tmplo,regdst.reglo); + + tmphi:=cg.GetIntRegister(list,OS_INT); + hreg:=cg.GetIntRegister(list,OS_INT); + cg.a_load_const_reg(list,OS_INT,$80000000,hreg); + // first add carry to one of the addends + list.concat(taicpu.op_reg_reg_reg(A_ADD, tmphi, regsrc.reghi, carry)); + + cg.a_load_const_reg(list,OS_INT,1,carry); + current_asmdata.getjumplabel(no_carry); + cg.a_cmp_reg_reg_label(list,OS_INT,OC_B,tmphi, regsrc.reghi,no_carry); + cg.a_load_const_reg(list,OS_INT,0,carry); + cg.a_label(list,no_carry); + + list.concat(taicpu.op_reg_reg_reg(A_SUB, carry, hreg, carry)); + // then add another addend + list.concat(taicpu.op_reg_reg_const(A_ADDI, regdst.reghi, tmphi, 0)); + end + end + else + begin + tmpreg64.reglo := cg.GetIntRegister(list,OS_S32); + tmpreg64.reghi := cg.GetIntRegister(list,OS_S32); + a_load64_const_reg(list,value,tmpreg64); + a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst); + end; + end; + OP_SUB: + begin + { for now, we take the simple approach } + tmpreg64.reglo := cg.GetIntRegister(list,OS_S32); + tmpreg64.reghi := cg.GetIntRegister(list,OS_S32); + a_load64_const_reg(list,value,tmpreg64); + a_op64_reg_reg_reg(list,op,size,tmpreg64,regsrc,regdst); + end; + else + internalerror(2020030901); + end; end;