emit_arm64_data_processing: Handle immediate carry in for shift instructions
This commit is contained in:
parent
db5db43fd4
commit
73b48448cb
1 changed files with 46 additions and 7 deletions
|
@ -291,7 +291,11 @@ void EmitIR<IR::Opcode::LogicalShiftLeft32>(oaknut::CodeGenerator& code, EmitCon
|
|||
auto Woperand = ctx.reg_alloc.ReadW(operand_arg);
|
||||
auto Wshift = ctx.reg_alloc.ReadW(shift_arg);
|
||||
auto Wcarry_in = ctx.reg_alloc.ReadW(carry_arg);
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift);
|
||||
} else {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
}
|
||||
ctx.reg_alloc.SpillFlags();
|
||||
|
||||
// TODO: Use RMIF
|
||||
|
@ -312,7 +316,11 @@ void EmitIR<IR::Opcode::LogicalShiftLeft32>(oaknut::CodeGenerator& code, EmitCon
|
|||
|
||||
code.l(zero);
|
||||
code.MOV(*Wresult, Woperand);
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
code.MOV(Wcarry_out, carry_arg.GetImmediateU32() << 29);
|
||||
} else {
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
}
|
||||
|
||||
code.l(end);
|
||||
}
|
||||
|
@ -421,7 +429,11 @@ void EmitIR<IR::Opcode::LogicalShiftRight32>(oaknut::CodeGenerator& code, EmitCo
|
|||
auto Woperand = ctx.reg_alloc.ReadW(operand_arg);
|
||||
auto Wshift = ctx.reg_alloc.ReadW(shift_arg);
|
||||
auto Wcarry_in = ctx.reg_alloc.ReadW(carry_arg);
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift);
|
||||
} else {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
}
|
||||
ctx.reg_alloc.SpillFlags();
|
||||
|
||||
// TODO: Use RMIF
|
||||
|
@ -442,7 +454,11 @@ void EmitIR<IR::Opcode::LogicalShiftRight32>(oaknut::CodeGenerator& code, EmitCo
|
|||
|
||||
code.l(zero);
|
||||
code.MOV(*Wresult, Woperand);
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
code.MOV(Wcarry_out, carry_arg.GetImmediateU32() << 29);
|
||||
} else {
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
}
|
||||
|
||||
code.l(end);
|
||||
}
|
||||
|
@ -541,7 +557,11 @@ void EmitIR<IR::Opcode::ArithmeticShiftRight32>(oaknut::CodeGenerator& code, Emi
|
|||
auto Woperand = ctx.reg_alloc.ReadW(operand_arg);
|
||||
auto Wshift = ctx.reg_alloc.ReadW(shift_arg);
|
||||
auto Wcarry_in = ctx.reg_alloc.ReadW(carry_arg);
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift);
|
||||
} else {
|
||||
RegAlloc::Realize(Wresult, Wcarry_out, Woperand, Wshift, Wcarry_in);
|
||||
}
|
||||
ctx.reg_alloc.SpillFlags();
|
||||
|
||||
// TODO: Use RMIF
|
||||
|
@ -568,7 +588,11 @@ void EmitIR<IR::Opcode::ArithmeticShiftRight32>(oaknut::CodeGenerator& code, Emi
|
|||
|
||||
code.l(zero);
|
||||
code.MOV(*Wresult, Woperand);
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
if (carry_arg.IsImmediate()) {
|
||||
code.MOV(Wcarry_out, carry_arg.GetImmediateU32() << 29);
|
||||
} else {
|
||||
code.MOV(*Wcarry_out, Wcarry_in);
|
||||
}
|
||||
|
||||
code.l(end);
|
||||
}
|
||||
|
@ -621,7 +645,22 @@ void EmitIR<IR::Opcode::RotateRight32>(oaknut::CodeGenerator& code, EmitContext&
|
|||
|
||||
code.ROR(Wresult, Woperand, Wshift);
|
||||
|
||||
if (carry_inst) {
|
||||
if (carry_inst && carry_arg.IsImmediate()) {
|
||||
const u32 carry_in = carry_arg.GetImmediateU32() << 29;
|
||||
auto Wcarry_out = ctx.reg_alloc.WriteW(carry_inst);
|
||||
RegAlloc::Realize(Wcarry_out);
|
||||
ctx.reg_alloc.SpillFlags();
|
||||
|
||||
code.TST(Wshift, 0xff);
|
||||
code.LSR(Wcarry_out, Wresult, 31 - 29);
|
||||
code.AND(Wcarry_out, Wcarry_out, 1 << 29);
|
||||
if (carry_in) {
|
||||
code.MOV(Wscratch0, carry_in);
|
||||
code.CSEL(Wcarry_out, Wscratch0, Wcarry_out, EQ);
|
||||
} else {
|
||||
code.CSEL(Wcarry_out, WZR, Wcarry_out, EQ);
|
||||
}
|
||||
} else if (carry_inst) {
|
||||
auto Wcarry_in = ctx.reg_alloc.ReadW(carry_arg);
|
||||
auto Wcarry_out = ctx.reg_alloc.WriteW(carry_inst);
|
||||
RegAlloc::Realize(Wcarry_out, Wcarry_in);
|
||||
|
|
Loading…
Reference in a new issue