-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
544 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
#region License | ||
/* | ||
* Copyright (C) 1999-2024 John Källén. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2, or (at your option) | ||
* any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; see the file COPYING. If not, write to | ||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
*/ | ||
#endregion | ||
|
||
using Reko.Core.Collections; | ||
using Reko.Core.Machine; | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
|
||
namespace Reko.Arch.RiscV | ||
{ | ||
public class LongConstantFuser : IEnumerable<MachineInstruction> | ||
{ | ||
private RiscVDisassembler dasm; | ||
|
||
public LongConstantFuser(RiscVDisassembler dasm) | ||
{ | ||
this.dasm = dasm; | ||
} | ||
|
||
public IEnumerator<MachineInstruction> GetEnumerator() | ||
{ | ||
ImmediateOperand immLo; | ||
var e = new LookaheadEnumerator<RiscVInstruction>(dasm); | ||
while (e.MoveNext()) | ||
{ | ||
var instrHi = e.Current; | ||
switch (instrHi.Mnemonic) | ||
{ | ||
case Mnemonic.auipc: | ||
if (!e.TryPeek(1, out var instrLo)) | ||
{ | ||
yield return e.Current; | ||
break; | ||
} | ||
if (instrLo.Mnemonic == Mnemonic.addi) | ||
{ | ||
if (instrHi.Operands[0] == instrLo.Operands[0] && | ||
instrLo.Operands[0] == instrLo.Operands[1]) | ||
{ | ||
// Mutate the auipc | ||
var immHi = (ImmediateOperand) instrHi.Operands[1]; | ||
immLo = (ImmediateOperand) instrLo.Operands[2]; | ||
var fullAddr = instrHi.Address + | ||
((immHi.Value.ToInt32() << 12) + | ||
immLo.Value.ToInt32()); | ||
var hiOp = new SliceOperand(SliceType.PcRelHi, immHi, fullAddr); | ||
var loOp = new SliceOperand(SliceType.PcRelLo, immLo, fullAddr); | ||
instrHi.Operands[1] = hiOp; | ||
instrLo.Operands[2] = loOp; | ||
} | ||
} | ||
else if (IsMemoryInstruction(instrLo.Mnemonic)) | ||
{ | ||
var memOp = (MemoryOperand) instrLo.Operands[1]; | ||
if (instrLo.Operands[0] == memOp.Base && | ||
memOp.Offset is ImmediateOperand imm) | ||
{ | ||
var immHi = (ImmediateOperand) instrHi.Operands[1]; | ||
immLo = imm; | ||
// Mutate the auipc and the memory operand | ||
var fullAddr = instrHi.Address + | ||
((immHi.Value.ToInt32() << 12) + | ||
immLo.Value.ToInt32()); | ||
var hiOp = new SliceOperand(SliceType.PcRelHi, immHi, fullAddr); | ||
var loOp = new SliceOperand(SliceType.PcRelLo, immLo, fullAddr); | ||
instrHi.Operands[1] = hiOp; | ||
instrLo.Operands[1] = loOp; | ||
} | ||
} | ||
yield return e.Current; | ||
break; | ||
case Mnemonic.lui: | ||
if (!e.TryPeek(1, out instrLo)) | ||
{ | ||
yield return e.Current; | ||
break; | ||
} | ||
if (instrLo.Mnemonic == Mnemonic.addi) | ||
{ | ||
if (instrHi.Operands[0] == instrLo.Operands[0] && | ||
instrLo.Operands[0] == instrLo.Operands[1]) | ||
{ | ||
// Mutate the auipc and the addi | ||
var immHi = (ImmediateOperand) instrHi.Operands[1]; | ||
immLo = (ImmediateOperand) instrLo.Operands[2]; | ||
var fullAddr = ImmediateOperand.Word32( | ||
(immHi.Value.ToInt32() << 12) + | ||
immLo.Value.ToInt32()); | ||
var hiOp = new SliceOperand(SliceType.PcRelHi, immHi, fullAddr); | ||
var loOp = new SliceOperand(SliceType.PcRelLo, immLo, fullAddr); | ||
instrHi.Operands[1] = hiOp; | ||
instrLo.Operands[2] = loOp; | ||
} | ||
} | ||
else if (IsMemoryInstruction(instrLo.Mnemonic)) | ||
{ | ||
var memOp = (MemoryOperand) instrLo.Operands[1]; | ||
if (instrLo.Operands[0] == memOp.Base && | ||
memOp.Offset is ImmediateOperand imm) | ||
{ | ||
immLo = imm; | ||
// Mutate the auipc and the memory operand | ||
var immHi = (ImmediateOperand) instrHi.Operands[1]; | ||
var fullAddr = ImmediateOperand.Word32( | ||
(immHi.Value.ToInt32() << 12) + | ||
immLo.Value.ToInt32()); | ||
var hiOp = new SliceOperand(SliceType.PcRelHi, immHi, fullAddr); | ||
var loOp = new SliceOperand(SliceType.PcRelLo, immLo, fullAddr); | ||
instrHi.Operands[1] = hiOp; | ||
instrLo.Operands[1] = loOp; | ||
} | ||
} | ||
yield return e.Current; | ||
break; | ||
default: | ||
yield return e.Current; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
private static bool IsMemoryInstruction(Mnemonic mnemonic) | ||
{ | ||
return mnemonic switch | ||
{ | ||
Mnemonic.c_ld or | ||
Mnemonic.c_lw or | ||
Mnemonic.c_sd or | ||
Mnemonic.c_sw or | ||
Mnemonic.lb or | ||
Mnemonic.lbu or | ||
Mnemonic.lh or | ||
Mnemonic.lhu or | ||
Mnemonic.lw or | ||
Mnemonic.lwu or | ||
Mnemonic.ld or | ||
Mnemonic.sb or | ||
Mnemonic.sh or | ||
Mnemonic.sw or | ||
Mnemonic.sd or | ||
Mnemonic.fsd or | ||
Mnemonic.fsw => true, | ||
_ => false, | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.