Compare commits

..

8 Commits

Author SHA1 Message Date
72e543e946 Prefer texture over textureSize for sampler type (#3132)
* Prefer texture over textureSize for sampler type

* Shader cache version bump
2022-02-18 02:44:46 +01:00
98c838b24c Use BitOperations methods and delete now unused BitUtils methods (#3134)
Replaces BitUtils.CountTrailingZeros/CountLeadingZeros/IsPowerOfTwo with BitOperations methods
2022-02-18 02:35:23 +01:00
63c9c64196 Move kernel syscall logs to new trace log level (#3137) 2022-02-18 02:14:05 +01:00
a113ed0811 Implement/Stub mnpp:app service and some hid calls (#3131)
* Implement/Stub mnpp:app service and some hid calls

This PR Implement/Stub the `mnpp:app` service (closes #3107) accordingly to RE, which seems to do some telemetry for China region only, so everything is stubbed.

This PR fixes some inconsistencies in the hid service too and stub EnableSixAxisSensorUnalteredPassthrough, IsSixAxisSensorUnalteredPassthroughEnabled, LoadSixAxisSensorCalibrationParameter, GetSixAxisSensorIcInformation calls (closes #3123 and closes #3124).

* Addresses Thog review
2022-02-18 02:00:06 +01:00
747876dc67 Decoders: Add IOpCode32HasSetFlags (#3136) 2022-02-18 01:33:43 +01:00
95cc18a7b4 Added trace log level (#3096)
* added trace log level

* use trace log level instead of debug ( #1547)

* alignment #1547

* moved trace logs toggle at the bottom #1547

* bumped config file version #3096

* added migration step #3096

* setting moved to the dev section #1547

* performance warning displayed when trace is enabled #1547
2022-02-17 21:08:07 -03:00
c017c77365 Change ServiceNv map creation logs to the Debug level (#3058) 2022-02-18 00:41:21 +01:00
98e05ee4b7 ARMeilleure: Thumb support (All T16 instructions) (#3105)
* Decoders: Add InITBlock argument

* OpCodeTable: Minor cleanup

* OpCodeTable: Remove existing thumb instruction implementations

* OpCodeTable: Prepare for thumb instructions

* OpCodeTables: Improve thumb fast lookup

* Tests: Prepare for thumb tests

* T16: Implement BX

* T16: Implement LSL/LSR/ASR (imm)

* T16: Implement ADDS, SUBS (reg)

* T16: Implement ADDS, SUBS (3-bit immediate)

* T16: Implement MOVS, CMP, ADDS, SUBS (8-bit immediate)

* T16: Implement ANDS, EORS, LSLS, LSRS, ASRS, ADCS, SBCS, RORS, TST, NEGS, CMP, CMN, ORRS, MULS, BICS, MVNS (low registers)

* T16: Implement ADD, CMP, MOV (high reg)

* T16: Implement BLX (reg)

* T16: Implement LDR (literal)

* T16: Implement {LDR,STR}{,H,B,SB,SH} (register)

* T16: Implement {LDR,STR}{,B,H} (immediate)

* T16: Implement LDR/STR (SP)

* T16: Implement ADR

* T16: Implement Add to SP (immediate)

* T16: Implement ADD/SUB (SP)

* T16: Implement SXTH, SXTB, UXTH, UTXB

* T16: Implement CBZ, CBNZ

* T16: Implement PUSH, POP

* T16: Implement REV, REV16, REVSH

* T16: Implement NOP

* T16: Implement LDM, STM

* T16: Implement SVC

* T16: Implement B (conditional)

* T16: Implement B (unconditional)

* T16: Implement IT

* fixup! T16: Implement ADD/SUB (SP)

* fixup! T16: Implement Add to SP (immediate)

* fixup! T16: Implement IT

* CpuTestThumb: Add randomized tests

* Remove inITBlock argument

* Address nits

* Use index to handle IfThenBlockState

* Reduce line noise

* fixup

* nit
2022-02-17 19:39:45 -03:00
85 changed files with 2143 additions and 226 deletions

View File

@ -195,12 +195,13 @@ namespace ARMeilleure.Decoders
ulong limitAddress)
{
ulong address = block.Address;
int itBlockSize = 0;
OpCode opCode;
do
{
if (address >= limitAddress)
if (address >= limitAddress && itBlockSize == 0)
{
break;
}
@ -210,6 +211,15 @@ namespace ARMeilleure.Decoders
block.OpCodes.Add(opCode);
address += (ulong)opCode.OpCodeSizeInBytes;
if (opCode is OpCodeT16IfThen it)
{
itBlockSize = it.IfThenBlockSize;
}
else if (itBlockSize > 0)
{
itBlockSize--;
}
}
while (!(IsBranch(opCode) || IsException(opCode)));
@ -345,7 +355,14 @@ namespace ARMeilleure.Decoders
}
else
{
return new OpCode(inst, address, opCode);
if (mode == ExecutionMode.Aarch32Thumb)
{
return new OpCodeT16(inst, address, opCode);
}
else
{
return new OpCode(inst, address, opCode);
}
}
}
}

View File

@ -0,0 +1,9 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32Adr
{
int Rd { get; }
int Immediate { get; }
}
}

View File

@ -1,10 +1,8 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32Alu : IOpCode32
interface IOpCode32Alu : IOpCode32, IOpCode32HasSetFlags
{
int Rd { get; }
int Rn { get; }
bool SetFlags { get; }
}
}

View File

@ -0,0 +1,9 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluImm : IOpCode32Alu
{
int Immediate { get; }
bool IsRotated { get; }
}
}

View File

@ -0,0 +1,10 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluRsImm : IOpCode32Alu
{
int Rm { get; }
int Immediate { get; }
ShiftType ShiftType { get; }
}
}

View File

@ -0,0 +1,10 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32AluRsReg : IOpCode32Alu
{
int Rm { get; }
int Rs { get; }
ShiftType ShiftType { get; }
}
}

View File

@ -0,0 +1,6 @@
namespace ARMeilleure.Decoders;
interface IOpCode32Exception
{
int Id { get; }
}

View File

@ -0,0 +1,7 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32HasSetFlags
{
bool? SetFlags { get; }
}
}

View File

@ -7,5 +7,9 @@ namespace ARMeilleure.Decoders
bool WBack { get; }
bool IsLoad { get; }
bool Index { get; }
bool Add { get; }
int Immediate { get; }
}
}

View File

@ -9,5 +9,7 @@ namespace ARMeilleure.Decoders
int PostOffset { get; }
bool IsLoad { get; }
int Offset { get; }
}
}

View File

@ -0,0 +1,7 @@
namespace ARMeilleure.Decoders
{
interface IOpCode32MemReg : IOpCode32Mem
{
int Rm { get; }
}
}

View File

@ -18,10 +18,9 @@ namespace ARMeilleure.Decoders
public OpCode(InstDescriptor inst, ulong address, int opCode)
{
Address = address;
RawOpCode = opCode;
Instruction = inst;
Address = address;
RawOpCode = opCode;
RegisterSize = RegisterSize.Int64;
}

View File

@ -5,7 +5,7 @@ namespace ARMeilleure.Decoders
public int Rd { get; }
public int Rn { get; }
public bool SetFlags { get; }
public bool? SetFlags { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Alu(inst, address, opCode);

View File

@ -2,7 +2,7 @@ using ARMeilleure.Common;
namespace ARMeilleure.Decoders
{
class OpCode32AluImm : OpCode32Alu
class OpCode32AluImm : OpCode32Alu, IOpCode32AluImm
{
public int Immediate { get; }

View File

@ -10,7 +10,7 @@
public bool NHigh { get; }
public bool MHigh { get; }
public bool R { get; }
public bool SetFlags { get; }
public bool? SetFlags { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluMla(inst, address, opCode);

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluRsImm : OpCode32Alu
class OpCode32AluRsImm : OpCode32Alu, IOpCode32AluRsImm
{
public int Rm { get; }
public int Immediate { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluRsReg : OpCode32Alu
class OpCode32AluRsReg : OpCode32Alu, IOpCode32AluRsReg
{
public int Rm { get; }
public int Rs { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32AluUmull : OpCode32
class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags
{
public int RdLo { get; }
public int RdHi { get; }
@ -10,7 +10,7 @@
public bool NHigh { get; }
public bool MHigh { get; }
public bool SetFlags { get; }
public bool? SetFlags { get; }
public DataOp DataOp { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32Exception : OpCode32
class OpCode32Exception : OpCode32, IOpCode32Exception
{
public int Id { get; }

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCode32MemReg : OpCode32Mem
class OpCode32MemReg : OpCode32Mem, IOpCode32MemReg
{
public int Rm { get; }

View File

@ -0,0 +1,24 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AddSubImm3: OpCodeT16, IOpCode32AluImm
{
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => null;
public int Immediate { get; }
public bool IsRotated { get; }
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubImm3(inst, address, opCode);
public OpCodeT16AddSubImm3(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rn = (opCode >> 3) & 0x7;
Immediate = (opCode >> 6) & 0x7;
IsRotated = false;
}
}
}

View File

@ -0,0 +1,20 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AddSubReg : OpCodeT16, IOpCode32AluReg
{
public int Rm { get; }
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => null;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubReg(inst, address, opCode);
public OpCodeT16AddSubReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rn = (opCode >> 3) & 0x7;
Rm = (opCode >> 6) & 0x7;
}
}
}

View File

@ -0,0 +1,23 @@
using ARMeilleure.State;
namespace ARMeilleure.Decoders
{
class OpCodeT16AddSubSp : OpCodeT16, IOpCode32AluImm
{
public int Rd => RegisterAlias.Aarch32Sp;
public int Rn => RegisterAlias.Aarch32Sp;
public bool? SetFlags => false;
public int Immediate { get; }
public bool IsRotated => false;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubSp(inst, address, opCode);
public OpCodeT16AddSubSp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = ((opCode >> 0) & 0x7f) << 2;
}
}
}

View File

@ -0,0 +1,20 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16Adr : OpCodeT16, IOpCode32Adr
{
public int Rd { get; }
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode);
public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 8) & 7;
int imm = (opCode & 0xff) << 2;
Immediate = (int)(GetPc() & 0xfffffffc) + imm;
}
}
}

View File

@ -1,22 +1,24 @@
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCodeT16AluImm8 : OpCodeT16, IOpCode32Alu
class OpCodeT16AluImm8 : OpCodeT16, IOpCode32AluImm
{
private int _rdn;
public int Rd { get; }
public int Rn { get; }
public int Rd => _rdn;
public int Rn => _rdn;
public bool SetFlags => false;
public bool? SetFlags => null;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImm8(inst, address, opCode);
public bool IsRotated { get; }
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImm8(inst, address, opCode);
public OpCodeT16AluImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 8) & 0x7;
Rn = (opCode >> 8) & 0x7;
Immediate = (opCode >> 0) & 0xff;
_rdn = (opCode >> 8) & 0x7;
IsRotated = false;
}
}
}
}

View File

@ -0,0 +1,24 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AluImmZero : OpCodeT16, IOpCode32AluImm
{
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => null;
public int Immediate { get; }
public bool IsRotated { get; }
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImmZero(inst, address, opCode);
public OpCodeT16AluImmZero(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rn = (opCode >> 3) & 0x7;
Immediate = 0;
IsRotated = false;
}
}
}

View File

@ -0,0 +1,20 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AluRegHigh : OpCodeT16, IOpCode32AluReg
{
public int Rm { get; }
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => false;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluRegHigh(inst, address, opCode);
public OpCodeT16AluRegHigh(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8);
Rn = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8);
Rm = (opCode >> 3) & 0xf;
}
}
}

View File

@ -0,0 +1,20 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AluRegLow : OpCodeT16, IOpCode32AluReg
{
public int Rm { get; }
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => null;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluRegLow(inst, address, opCode);
public OpCodeT16AluRegLow(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rn = (opCode >> 0) & 0x7;
Rm = (opCode >> 3) & 0x7;
}
}
}

View File

@ -0,0 +1,22 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AluUx : OpCodeT16, IOpCode32AluUx
{
public int Rm { get; }
public int Rd { get; }
public int Rn { get; }
public bool? SetFlags => false;
public int RotateBits => 0;
public bool Add => false;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluUx(inst, address, opCode);
public OpCodeT16AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rm = (opCode >> 3) & 0x7;
}
}
}

View File

@ -0,0 +1,15 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16BImm11 : OpCode32, IOpCode32BImm
{
public long Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImm11(inst, address, opCode);
public OpCodeT16BImm11(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
int imm = (opCode << 21) >> 20;
Immediate = GetPc() + imm;
}
}
}

View File

@ -0,0 +1,17 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16BImm8 : OpCode32, IOpCode32BImm
{
public long Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImm8(inst, address, opCode);
public OpCodeT16BImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Cond = (Condition)((opCode >> 8) & 0xf);
int imm = (opCode << 24) >> 23;
Immediate = GetPc() + imm;
}
}
}

View File

@ -0,0 +1,19 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16BImmCmp : OpCodeT16
{
public int Rn { get; }
public int Immediate { get; }
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImmCmp(inst, address, opCode);
public OpCodeT16BImmCmp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rn = (opCode >> 0) & 0x7;
int imm = ((opCode >> 2) & 0x3e) | ((opCode >> 3) & 0x40);
Immediate = (int)GetPc() + imm;
}
}
}

View File

@ -1,4 +1,4 @@
namespace ARMeilleure.Decoders
namespace ARMeilleure.Decoders
{
class OpCodeT16BReg : OpCodeT16, IOpCode32BReg
{
@ -11,4 +11,4 @@ namespace ARMeilleure.Decoders
Rm = (opCode >> 3) & 0xf;
}
}
}
}

View File

@ -0,0 +1,14 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16Exception : OpCodeT16, IOpCode32Exception
{
public int Id { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Exception(inst, address, opCode);
public OpCodeT16Exception(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Id = opCode & 0xFF;
}
}
}

View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Reflection.Emit;
namespace ARMeilleure.Decoders
{
class OpCodeT16IfThen : OpCodeT16
{
public Condition[] IfThenBlockConds { get; }
public int IfThenBlockSize { get { return IfThenBlockConds.Length; } }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16IfThen(inst, address, opCode);
public OpCodeT16IfThen(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
List<Condition> conds = new();
int cond = (opCode >> 4) & 0xf;
int mask = opCode & 0xf;
conds.Add((Condition)cond);
while ((mask & 7) != 0)
{
int newLsb = (mask >> 3) & 1;
cond = (cond & 0xe) | newLsb;
mask <<= 1;
conds.Add((Condition)cond);
}
IfThenBlockConds = conds.ToArray();
}
}
}

View File

@ -0,0 +1,58 @@
using ARMeilleure.Instructions;
using System;
namespace ARMeilleure.Decoders
{
class OpCodeT16MemImm5 : OpCodeT16, IOpCode32Mem
{
public int Rt { get; }
public int Rn { get; }
public bool WBack => false;
public bool IsLoad { get; }
public bool Index => true;
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemImm5(inst, address, opCode);
public OpCodeT16MemImm5(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt = (opCode >> 0) & 7;
Rn = (opCode >> 3) & 7;
switch (inst.Name)
{
case InstName.Ldr:
case InstName.Ldrb:
case InstName.Ldrh:
IsLoad = true;
break;
case InstName.Str:
case InstName.Strb:
case InstName.Strh:
IsLoad = false;
break;
}
switch (inst.Name)
{
case InstName.Str:
case InstName.Ldr:
Immediate = ((opCode >> 6) & 0x1f) << 2;
break;
case InstName.Strb:
case InstName.Ldrb:
Immediate = ((opCode >> 6) & 0x1f);
break;
case InstName.Strh:
case InstName.Ldrh:
Immediate = ((opCode >> 6) & 0x1f) << 1;
break;
default:
throw new InvalidOperationException();
}
}
}
}

View File

@ -0,0 +1,26 @@
using ARMeilleure.State;
namespace ARMeilleure.Decoders
{
class OpCodeT16MemLit : OpCodeT16, IOpCode32Mem
{
public int Rt { get; }
public int Rn => RegisterAlias.Aarch32Pc;
public bool WBack => false;
public bool IsLoad => true;
public bool Index => true;
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemLit(inst, address, opCode);
public OpCodeT16MemLit(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt = (opCode >> 8) & 7;
Immediate = (opCode & 0xff) << 2;
}
}
}

View File

@ -0,0 +1,34 @@
using ARMeilleure.Instructions;
using System;
using System.Numerics;
namespace ARMeilleure.Decoders
{
class OpCodeT16MemMult : OpCodeT16, IOpCode32MemMult
{
public int Rn { get; }
public int RegisterMask { get; }
public int PostOffset { get; }
public bool IsLoad { get; }
public int Offset { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemMult(inst, address, opCode);
public OpCodeT16MemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
RegisterMask = opCode & 0xff;
Rn = (opCode >> 8) & 7;
int regCount = BitOperations.PopCount((uint)RegisterMask);
Offset = 0;
PostOffset = 4 * regCount;
IsLoad = inst.Name switch
{
InstName.Ldm => true,
InstName.Stm => false,
_ => throw new InvalidOperationException()
};
}
}
}

View File

@ -0,0 +1,27 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16MemReg : OpCodeT16, IOpCode32MemReg
{
public int Rm { get; }
public int Rt { get; }
public int Rn { get; }
public bool WBack => false;
public bool IsLoad { get; }
public bool Index => true;
public bool Add => true;
public int Immediate => throw new System.InvalidOperationException();
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemReg(inst, address, opCode);
public OpCodeT16MemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt = (opCode >> 0) & 7;
Rn = (opCode >> 3) & 7;
Rm = (opCode >> 6) & 7;
IsLoad = ((opCode >> 9) & 7) >= 3;
}
}
}

View File

@ -0,0 +1,28 @@
using ARMeilleure.State;
namespace ARMeilleure.Decoders
{
class OpCodeT16MemSp : OpCodeT16, IOpCode32Mem
{
public int Rt { get; }
public int Rn => RegisterAlias.Aarch32Sp;
public bool WBack => false;
public bool IsLoad { get; }
public bool Index => true;
public bool Add => true;
public int Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemSp(inst, address, opCode);
public OpCodeT16MemSp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rt = (opCode >> 8) & 7;
IsLoad = ((opCode >> 11) & 1) != 0;
Immediate = ((opCode >> 0) & 0xff) << 2;
}
}
}

View File

@ -0,0 +1,42 @@
using ARMeilleure.Instructions;
using ARMeilleure.State;
using System;
using System.Numerics;
namespace ARMeilleure.Decoders
{
class OpCodeT16MemStack : OpCodeT16, IOpCode32MemMult
{
public int Rn => RegisterAlias.Aarch32Sp;
public int RegisterMask { get; }
public int PostOffset { get; }
public bool IsLoad { get; }
public int Offset { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemStack(inst, address, opCode);
public OpCodeT16MemStack(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
int extra = (opCode >> 8) & 1;
int regCount = BitOperations.PopCount((uint)opCode & 0x1ff);
switch (inst.Name)
{
case InstName.Push:
RegisterMask = (opCode & 0xff) | (extra << 14);
IsLoad = false;
Offset = -4 * regCount;
PostOffset = -4 * regCount;
break;
case InstName.Pop:
RegisterMask = (opCode & 0xff) | (extra << 15);
IsLoad = true;
Offset = 0;
PostOffset = 4 * regCount;
break;
default:
throw new InvalidOperationException();
}
}
}
}

View File

@ -0,0 +1,24 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16ShiftImm : OpCodeT16, IOpCode32AluRsImm
{
public int Rd { get; }
public int Rn { get; }
public int Rm { get; }
public int Immediate { get; }
public ShiftType ShiftType { get; }
public bool? SetFlags => null;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16ShiftImm(inst, address, opCode);
public OpCodeT16ShiftImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 0x7;
Rm = (opCode >> 3) & 0x7;
Immediate = (opCode >> 6) & 0x1F;
ShiftType = (ShiftType)((opCode >> 11) & 3);
}
}
}

View File

@ -0,0 +1,27 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16ShiftReg : OpCodeT16, IOpCode32AluRsReg
{
public int Rm { get; }
public int Rs { get; }
public int Rd { get; }
public int Rn { get; }
public ShiftType ShiftType { get; }
public bool? SetFlags => null;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16ShiftReg(inst, address, opCode);
public OpCodeT16ShiftReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 0) & 7;
Rm = (opCode >> 0) & 7;
Rn = (opCode >> 3) & 7;
Rs = (opCode >> 3) & 7;
ShiftType = (ShiftType)(((opCode >> 6) & 1) | ((opCode >> 7) & 2));
}
}
}

View File

@ -0,0 +1,24 @@
using ARMeilleure.State;
namespace ARMeilleure.Decoders
{
class OpCodeT16SpRel : OpCodeT16, IOpCode32AluImm
{
public int Rd { get; }
public int Rn => RegisterAlias.Aarch32Sp;
public bool? SetFlags => false;
public int Immediate { get; }
public bool IsRotated => false;
public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16SpRel(inst, address, opCode);
public OpCodeT16SpRel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Rd = (opCode >> 8) & 0x7;
Immediate = ((opCode >> 0) & 0xff) << 2;
}
}
}

View File

@ -1,5 +1,4 @@
using ARMeilleure.Instructions;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
@ -29,9 +28,9 @@ namespace ARMeilleure.Decoders
}
}
private static List<InstInfo> AllInstA32 = new List<InstInfo>();
private static List<InstInfo> AllInstT32 = new List<InstInfo>();
private static List<InstInfo> AllInstA64 = new List<InstInfo>();
private static List<InstInfo> AllInstA32 = new();
private static List<InstInfo> AllInstT32 = new();
private static List<InstInfo> AllInstA64 = new();
private static InstInfo[][] InstA32FastLookup = new InstInfo[FastLookupSize][];
private static InstInfo[][] InstT32FastLookup = new InstInfo[FastLookupSize][];
@ -628,7 +627,7 @@ namespace ARMeilleure.Decoders
SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", InstName.Zip2_V, InstEmit.Zip2_V, OpCodeSimdReg.Create);
#endregion
#region "OpCode Table (AArch32)"
#region "OpCode Table (AArch32, A32)"
// Base
SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluImm.Create);
SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluRsImm.Create);
@ -649,7 +648,6 @@ namespace ARMeilleure.Decoders
SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, OpCode32BImm.Create);
SetA32("<<<<000100101111111111110011xxxx", InstName.Blx, InstEmit32.Blxr, OpCode32BReg.Create);
SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, OpCode32BReg.Create);
SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create);
SetA32("11110101011111111111000000011111", InstName.Clrex, InstEmit32.Clrex, OpCode32.Create);
SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, OpCode32AluReg.Create);
SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluImm.Create);
@ -702,7 +700,6 @@ namespace ARMeilleure.Decoders
SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluRsImm.Create);
SetA32("<<<<0001101x0000xxxxxxxx0xx1xxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluRsReg.Create);
SetA32("<<<<00110000xxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluImm16.Create);
SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluImm8.Create);
SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCode32AluImm16.Create);
SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, OpCode32System.Create);
SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, OpCode32System.Create);
@ -975,12 +972,85 @@ namespace ARMeilleure.Decoders
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create);
#endregion
FillFastLookupTable(InstA32FastLookup, AllInstA32);
FillFastLookupTable(InstT32FastLookup, AllInstT32);
FillFastLookupTable(InstA64FastLookup, AllInstA64);
#region "OpCode Table (AArch32, T16/T32)"
// T16
SetT16("000<<xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftImm.Create);
SetT16("0001100xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubReg.Create);
SetT16("0001101xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubReg.Create);
SetT16("0001110xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubImm3.Create);
SetT16("0001111xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubImm3.Create);
SetT16("00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluImm8.Create);
SetT16("00101xxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluImm8.Create);
SetT16("00110xxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluImm8.Create);
SetT16("00111xxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AluImm8.Create);
SetT16("0100000000xxxxxx", InstName.And, InstEmit32.And, OpCodeT16AluRegLow.Create);
SetT16("0100000001xxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT16AluRegLow.Create);
SetT16("0100000010xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create);
SetT16("0100000011xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create);
SetT16("0100000100xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create);
SetT16("0100000101xxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT16AluRegLow.Create);
SetT16("0100000110xxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT16AluRegLow.Create);
SetT16("0100000111xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create);
SetT16("0100001000xxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT16AluRegLow.Create);
SetT16("0100001001xxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT16AluImmZero.Create);
SetT16("0100001010xxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegLow.Create);
SetT16("0100001011xxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT16AluRegLow.Create);
SetT16("0100001100xxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT16AluRegLow.Create);
SetT16("0100001101xxxxxx", InstName.Mul, InstEmit32.Mul, OpCodeT16AluRegLow.Create);
SetT16("0100001110xxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT16AluRegLow.Create);
SetT16("0100001111xxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT16AluRegLow.Create);
SetT16("01000100xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluRegHigh.Create);
SetT16("01000101xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegHigh.Create);
SetT16("01000110xxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluRegHigh.Create);
SetT16("010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create);
SetT16("010001111xxxx000", InstName.Blx, InstEmit32.Blx, OpCodeT16BReg.Create);
SetT16("01001xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemLit.Create);
SetT16("0101000xxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemReg.Create);
SetT16("0101001xxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemReg.Create);
SetT16("0101010xxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT16MemReg.Create);
SetT16("0101011xxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT16MemReg.Create);
SetT16("0101100xxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemReg.Create);
SetT16("0101101xxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT16MemReg.Create);
SetT16("0101110xxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT16MemReg.Create);
SetT16("0101111xxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT16MemReg.Create);
SetT16("01100xxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemImm5.Create);
SetT16("01101xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemImm5.Create);
SetT16("01110xxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT16MemImm5.Create);
SetT16("01111xxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT16MemImm5.Create);
SetT16("10000xxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemImm5.Create);
SetT16("10001xxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT16MemImm5.Create);
SetT16("10010xxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemSp.Create);
SetT16("10011xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemSp.Create);
SetT16("10100xxxxxxxxxxx", InstName.Adr, InstEmit32.Adr, OpCodeT16Adr.Create);
SetT16("10101xxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16SpRel.Create);
SetT16("101100000xxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubSp.Create);
SetT16("101100001xxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubSp.Create);
SetT16("1011001000xxxxxx", InstName.Sxth, InstEmit32.Sxth, OpCodeT16AluUx.Create);
SetT16("1011001001xxxxxx", InstName.Sxtb, InstEmit32.Sxtb, OpCodeT16AluUx.Create);
SetT16("1011001010xxxxxx", InstName.Uxth, InstEmit32.Uxth, OpCodeT16AluUx.Create);
SetT16("1011001011xxxxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCodeT16AluUx.Create);
SetT16("101100x1xxxxxxxx", InstName.Cbz, InstEmit32.Cbz, OpCodeT16BImmCmp.Create);
SetT16("1011010xxxxxxxxx", InstName.Push, InstEmit32.Stm, OpCodeT16MemStack.Create);
SetT16("1011101000xxxxxx", InstName.Rev, InstEmit32.Rev, OpCodeT16AluRegLow.Create);
SetT16("1011101001xxxxxx", InstName.Rev16, InstEmit32.Rev16, OpCodeT16AluRegLow.Create);
SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create);
SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create);
SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create);
SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create);
SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create);
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
#endregion
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
FillFastLookupTable(InstA64FastLookup, AllInstA64, ToFastLookupIndexA);
}
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts)
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> ToFastLookupIndex)
{
List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
@ -1011,20 +1081,27 @@ namespace ARMeilleure.Decoders
private static void SetA32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{
Set(encoding, ExecutionMode.Aarch32Arm, new InstDescriptor(name, emitter), makeOp);
Set(encoding, AllInstA32, new InstDescriptor(name, emitter), makeOp);
}
private static void SetT16(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{
encoding = "xxxxxxxxxxxxxxxx" + encoding;
Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp);
}
private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{
Set(encoding, ExecutionMode.Aarch32Thumb, new InstDescriptor(name, emitter), makeOp);
encoding = encoding.Substring(16) + encoding.Substring(0, 16);
Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp);
}
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{
Set(encoding, ExecutionMode.Aarch64, new InstDescriptor(name, emitter), makeOp);
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);
}
private static void Set(string encoding, ExecutionMode mode, InstDescriptor inst, MakeOp makeOp)
private static void Set(string encoding, List<InstInfo> list, InstDescriptor inst, MakeOp makeOp)
{
int bit = encoding.Length - 1;
int value = 0;
@ -1073,7 +1150,7 @@ namespace ARMeilleure.Decoders
if (xBits == 0)
{
InsertInst(new InstInfo(xMask, value, inst, makeOp), mode);
list.Add(new InstInfo(xMask, value, inst, makeOp));
return;
}
@ -1089,34 +1166,24 @@ namespace ARMeilleure.Decoders
if (mask != blacklisted)
{
InsertInst(new InstInfo(xMask, value | mask, inst, makeOp), mode);
list.Add(new InstInfo(xMask, value | mask, inst, makeOp));
}
}
}
private static void InsertInst(InstInfo info, ExecutionMode mode)
{
switch (mode)
{
case ExecutionMode.Aarch32Arm: AllInstA32.Add(info); break;
case ExecutionMode.Aarch32Thumb: AllInstT32.Add(info); break;
case ExecutionMode.Aarch64: AllInstA64.Add(info); break;
}
}
public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode)
{
return GetInstFromList(InstA32FastLookup[ToFastLookupIndex(opCode)], opCode);
return GetInstFromList(InstA32FastLookup[ToFastLookupIndexA(opCode)], opCode);
}
public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode)
{
return GetInstFromList(InstT32FastLookup[ToFastLookupIndex(opCode)], opCode);
return GetInstFromList(InstT32FastLookup[ToFastLookupIndexT(opCode)], opCode);
}
public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode)
{
return GetInstFromList(InstA64FastLookup[ToFastLookupIndex(opCode)], opCode);
return GetInstFromList(InstA64FastLookup[ToFastLookupIndexA(opCode)], opCode);
}
private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)
@ -1132,9 +1199,14 @@ namespace ARMeilleure.Decoders
return (new InstDescriptor(InstName.Und, InstEmit.Und), null);
}
private static int ToFastLookupIndex(int value)
private static int ToFastLookupIndexA(int value)
{
return ((value >> 10) & 0x00F) | ((value >> 18) & 0xFF0);
}
private static int ToFastLookupIndexT(int value)
{
return (value >> 4) & 0xFFF;
}
}
}

View File

@ -20,7 +20,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Add(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -44,7 +44,7 @@ namespace ARMeilleure.Instructions
res = context.Add(res, carry);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -64,7 +64,7 @@ namespace ARMeilleure.Instructions
Operand res = context.BitwiseAnd(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -110,7 +110,7 @@ namespace ARMeilleure.Instructions
Operand res = context.BitwiseAnd(n, context.BitwiseNot(m));
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -161,7 +161,7 @@ namespace ARMeilleure.Instructions
Operand res = context.BitwiseExclusiveOr(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
Operand m = GetAluM(context);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, m);
}
@ -204,7 +204,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Multiply(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -219,7 +219,7 @@ namespace ARMeilleure.Instructions
Operand res = context.BitwiseNot(m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -236,7 +236,7 @@ namespace ARMeilleure.Instructions
Operand res = context.BitwiseOr(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -315,7 +315,7 @@ namespace ARMeilleure.Instructions
res = context.Subtract(res, borrow);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -335,7 +335,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Subtract(m, n);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -359,7 +359,7 @@ namespace ARMeilleure.Instructions
res = context.Subtract(res, borrow);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -420,7 +420,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Subtract(n, m);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
@ -836,7 +836,7 @@ namespace ARMeilleure.Instructions
{
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
EmitGenericAluStoreA32(context, op.Rd, ShouldSetFlags(context), value);
}
}
}

View File

@ -12,6 +12,18 @@ namespace ARMeilleure.Instructions
{
static class InstEmitAluHelper
{
public static bool ShouldSetFlags(ArmEmitterContext context)
{
IOpCode32HasSetFlags op = (IOpCode32HasSetFlags)context.CurrOp;
if (op.SetFlags == null)
{
return !context.IsInIfThenBlock;
}
return op.SetFlags.Value;
}
public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d)
{
SetFlag(context, PState.NFlag, context.ICompareLess (d, Const(d.Type, 0)));
@ -183,9 +195,9 @@ namespace ARMeilleure.Instructions
switch (context.CurrOp)
{
// ARM32.
case OpCode32AluImm op:
case IOpCode32AluImm op:
{
if (op.SetFlags && op.IsRotated)
if (ShouldSetFlags(context) && op.IsRotated)
{
SetFlag(context, PState.CFlag, Const((uint)op.Immediate >> 31));
}
@ -195,10 +207,8 @@ namespace ARMeilleure.Instructions
case OpCode32AluImm16 op: return Const(op.Immediate);
case OpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case OpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
case OpCodeT16AluImm8 op: return Const(op.Immediate);
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
case IOpCode32AluReg op: return GetIntA32(context, op.Rm);
@ -249,7 +259,7 @@ namespace ARMeilleure.Instructions
}
// ARM32 helpers.
public static Operand GetMShiftedByImmediate(ArmEmitterContext context, OpCode32AluRsImm op, bool setCarry)
public static Operand GetMShiftedByImmediate(ArmEmitterContext context, IOpCode32AluRsImm op, bool setCarry)
{
Operand m = GetIntA32(context, op.Rm);
@ -267,7 +277,7 @@ namespace ARMeilleure.Instructions
if (shift != 0)
{
setCarry &= op.SetFlags;
setCarry &= ShouldSetFlags(context);
switch (op.ShiftType)
{
@ -305,7 +315,7 @@ namespace ARMeilleure.Instructions
return shift;
}
public static Operand GetMShiftedByReg(ArmEmitterContext context, OpCode32AluRsReg op, bool setCarry)
public static Operand GetMShiftedByReg(ArmEmitterContext context, IOpCode32AluRsReg op, bool setCarry)
{
Operand m = GetIntA32(context, op.Rm);
Operand s = context.ZeroExtend8(OperandType.I32, GetIntA32(context, op.Rs));
@ -314,7 +324,7 @@ namespace ARMeilleure.Instructions
Operand zeroResult = m;
Operand shiftResult = m;
setCarry &= op.SetFlags;
setCarry &= ShouldSetFlags(context);
switch (op.ShiftType)
{

View File

@ -20,11 +20,11 @@ namespace ARMeilleure.Instructions
private static void EmitExceptionCall(ArmEmitterContext context, string name)
{
OpCode32Exception op = (OpCode32Exception)context.CurrOp;
IOpCode32Exception op = (IOpCode32Exception)context.CurrOp;
context.StoreToContext();
context.Call(typeof(NativeInterface).GetMethod(name), Const(op.Address), Const(op.Id));
context.Call(typeof(NativeInterface).GetMethod(name), Const(((IOpCode)op).Address), Const(op.Id));
context.LoadFromContext();

View File

@ -64,7 +64,7 @@ namespace ARMeilleure.Instructions
bool isThumb = IsThumb(context.CurrOp);
uint currentPc = isThumb
? pc | 1
? (pc - 2) | 1
: pc - 4;
SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
@ -80,5 +80,32 @@ namespace ARMeilleure.Instructions
EmitBxWritePc(context, GetIntA32(context, op.Rm), op.Rm);
}
public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
private static void EmitCb(ArmEmitterContext context, bool onNotZero)
{
OpCodeT16BImmCmp op = (OpCodeT16BImmCmp)context.CurrOp;
Operand value = GetIntOrZR(context, op.Rn);
Operand lblTarget = context.GetLabel((ulong)op.Immediate);
if (onNotZero)
{
context.BranchIfTrue(lblTarget, value);
}
else
{
context.BranchIfFalse(lblTarget, value);
}
}
public static void It(ArmEmitterContext context)
{
OpCodeT16IfThen op = (OpCodeT16IfThen)context.CurrOp;
context.SetIfThenBlockState(op.IfThenBlockConds);
}
}
}

View File

@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions
public static void Ldm(ArmEmitterContext context)
{
OpCode32MemMult op = (OpCode32MemMult)context.CurrOp;
IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp;
Operand n = GetIntA32(context, op.Rn);
@ -95,7 +95,7 @@ namespace ARMeilleure.Instructions
public static void Stm(ArmEmitterContext context)
{
OpCode32MemMult op = (OpCode32MemMult)context.CurrOp;
IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp;
Operand n = context.Copy(GetIntA32(context, op.Rn));
@ -151,7 +151,7 @@ namespace ARMeilleure.Instructions
private static void EmitLoadOrStore(ArmEmitterContext context, int size, AccessType accType)
{
OpCode32Mem op = (OpCode32Mem)context.CurrOp;
IOpCode32Mem op = (IOpCode32Mem)context.CurrOp;
Operand n = context.Copy(GetIntA32AlignedPC(context, op.Rn));
Operand m = GetMemM(context, setCarry: false);
@ -255,5 +255,11 @@ namespace ARMeilleure.Instructions
}
}
}
public static void Adr(ArmEmitterContext context)
{
IOpCode32Adr op = (IOpCode32Adr)context.CurrOp;
SetIntA32(context, op.Rd, Const(op.Immediate));
}
}
}

View File

@ -549,9 +549,9 @@ namespace ARMeilleure.Instructions
{
case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
case OpCode32MemReg op: return GetIntA32(context, op.Rm);
case IOpCode32MemReg op: return GetIntA32(context, op.Rm);
case OpCode32Mem op: return Const(op.Immediate);
case IOpCode32Mem op: return Const(op.Immediate);
case OpCode32SimdMemImm op: return Const(op.Immediate);

View File

@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Add(a, context.Multiply(n, m));
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
@ -250,13 +250,13 @@ namespace ARMeilleure.Instructions
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi);
EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo);
}
public static void Smulw_(ArmEmitterContext context)
@ -320,13 +320,13 @@ namespace ARMeilleure.Instructions
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi);
EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo);
}
private static void EmitMlal(ArmEmitterContext context, bool signed)
@ -356,13 +356,13 @@ namespace ARMeilleure.Instructions
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res);
if (op.SetFlags)
if (ShouldSetFlags(context))
{
EmitNZFlagsCheck(context, res);
}
EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi);
EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo);
}
private static void UpdateQFlag(ArmEmitterContext context, Operand q)

View File

@ -48,6 +48,7 @@ namespace ARMeilleure.Instructions
Extr,
Hint,
Isb,
It,
Ldar,
Ldaxp,
Ldaxr,
@ -512,6 +513,8 @@ namespace ARMeilleure.Instructions
Mvn,
Pkh,
Pld,
Pop,
Push,
Rev,
Revsh,
Rsb,

View File

@ -54,6 +54,11 @@ namespace ARMeilleure.Translation
public bool HighCq { get; }
public Aarch32Mode Mode { get; }
private int _ifThenBlockStateIndex = 0;
private Condition[] _ifThenBlockState = { };
public bool IsInIfThenBlock => _ifThenBlockStateIndex < _ifThenBlockState.Length;
public Condition CurrentIfThenBlockCond => _ifThenBlockState[_ifThenBlockStateIndex];
public ArmEmitterContext(
IMemoryManager memory,
EntryTable<uint> countTable,
@ -196,5 +201,19 @@ namespace ARMeilleure.Translation
return default;
}
public void SetIfThenBlockState(Condition[] state)
{
_ifThenBlockState = state;
_ifThenBlockStateIndex = 0;
}
public void AdvanceIfThenBlockState()
{
if (IsInIfThenBlock)
{
_ifThenBlockStateIndex++;
}
}
}
}

View File

@ -380,6 +380,13 @@ namespace ARMeilleure.Translation
Operand lblPredicateSkip = default;
if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al)
{
lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert());
}
if (opCode is OpCode32 op && op.Cond < Condition.Al)
{
lblPredicateSkip = Label();
@ -400,6 +407,11 @@ namespace ARMeilleure.Translation
{
context.MarkLabel(lblPredicateSkip);
}
if (context.IsInIfThenBlock && opCode.Instruction.Name != InstName.It)
{
context.AdvanceIfThenBlockState();
}
}
}
}

View File

@ -39,6 +39,7 @@ namespace Ryujinx.Common.Logging
ServiceLm,
ServiceMii,
ServiceMm,
ServiceMnpp,
ServiceNfc,
ServiceNfp,
ServiceNgct,

View File

@ -9,6 +9,7 @@ namespace Ryujinx.Common.Logging
Error,
Guest,
AccessLog,
Notice
Notice,
Trace
}
}

View File

@ -90,6 +90,7 @@ namespace Ryujinx.Common.Logging
public static Log? Guest { get; private set; }
public static Log? AccessLog { get; private set; }
public static Log? Stub { get; private set; }
public static Log? Trace { get; private set; }
public static Log Notice { get; } // Always enabled
static Logger()
@ -117,6 +118,7 @@ namespace Ryujinx.Common.Logging
Error = new Log(LogLevel.Error);
Warning = new Log(LogLevel.Warning);
Info = new Log(LogLevel.Info);
Trace = new Log(LogLevel.Trace);
}
public static void RestartTime()
@ -172,7 +174,7 @@ namespace Ryujinx.Common.Logging
public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
{
var logs = new Log?[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub };
var logs = new Log?[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
List<LogLevel> levels = new List<LogLevel>(logs.Length);
foreach (var log in logs)
{
@ -196,6 +198,7 @@ namespace Ryujinx.Common.Logging
case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break;
case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog): new Log?(); break;
case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break;
case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break;
default: throw new ArgumentException("Unknown Log Level");
}
}

View File

@ -17,6 +17,7 @@ namespace Ryujinx.Common.Logging
LogLevel.Error => ConsoleColor.Red,
LogLevel.Stub => ConsoleColor.DarkGray,
LogLevel.Notice => ConsoleColor.Cyan,
LogLevel.Trace => ConsoleColor.DarkCyan,
_ => ConsoleColor.Gray,
};

View File

@ -1,11 +1,10 @@
using System;
using System.Numerics;
namespace Ryujinx.Common
{
public static class BitUtils
{
private static ReadOnlySpan<byte> ClzNibbleTbl => new byte[] { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
public static uint AlignUp(uint value, int size)
{
return (uint)AlignUp((int)value, size);
@ -76,60 +75,7 @@ namespace Ryujinx.Common
public static int Pow2RoundDown(int value)
{
return IsPowerOfTwo32(value) ? value : Pow2RoundUp(value) >> 1;
}
public static bool IsPowerOfTwo32(int value)
{
return value != 0 && (value & (value - 1)) == 0;
}
public static bool IsPowerOfTwo64(long value)
{
return value != 0 && (value & (value - 1)) == 0;
}
public static int CountLeadingZeros32(int value)
{
return (int)CountLeadingZeros((ulong)value, 32);
}
public static int CountLeadingZeros64(long value)
{
return (int)CountLeadingZeros((ulong)value, 64);
}
private static ulong CountLeadingZeros(ulong value, int size)
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
public static int CountTrailingZeros32(int value)
{
int count = 0;
while (((value >> count) & 1) == 0)
{
count++;
}
return count;
return BitOperations.IsPow2(value) ? value : Pow2RoundUp(value) >> 1;
}
public static long ReverseBits64(long value)

View File

@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary>
/// Version of the codegen (to be changed when codegen or guest format change).
/// </summary>
private const ulong ShaderCodeGenVersion = 3063;
private const ulong ShaderCodeGenVersion = 3132;
// Progress reporting helpers
private volatile int _shaderCount;

View File

@ -369,7 +369,7 @@ namespace Ryujinx.Graphics.Shader.Translation
inst &= Instruction.Mask;
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
bool accurateType = inst != Instruction.Lod;
bool accurateType = inst != Instruction.Lod && inst != Instruction.TextureSize;
bool coherent = flags.HasFlag(TextureFlags.Coherent);
if (isImage)

View File

@ -1,4 +1,5 @@
using Ryujinx.Common;
using System.Numerics;
using System.Runtime.CompilerServices;
using static Ryujinx.Graphics.Texture.BlockLinearConstants;
@ -47,15 +48,15 @@ namespace Ryujinx.Graphics.Texture
{
_texBpp = bpp;
_bppShift = BitUtils.CountTrailingZeros32(bpp);
_bppShift = BitOperations.TrailingZeroCount(bpp);
_bhMask = gobBlocksInY - 1;
_bdMask = gobBlocksInZ - 1;
_bhShift = BitUtils.CountTrailingZeros32(gobBlocksInY);
_bdShift = BitUtils.CountTrailingZeros32(gobBlocksInZ);
_bhShift = BitOperations.TrailingZeroCount(gobBlocksInY);
_bdShift = BitOperations.TrailingZeroCount(gobBlocksInZ);
_xShift = BitUtils.CountTrailingZeros32(GobSize * gobBlocksInY * gobBlocksInZ);
_xShift = BitOperations.TrailingZeroCount(GobSize * gobBlocksInY * gobBlocksInZ);
RobAndSliceSizes rsSizes = GetRobAndSliceSizes(width, height, gobBlocksInY, gobBlocksInZ);

View File

@ -1,4 +1,5 @@
using Ryujinx.Common;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Kernel.Common
{
@ -41,10 +42,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
range++;
// This is log2(Range) plus one.
int nextRangeLog2 = 64 - BitUtils.CountLeadingZeros64(range);
int nextRangeLog2 = 64 - BitOperations.LeadingZeroCount((ulong)range);
// If Range is already power of 2, subtract one to use log2(Range) directly.
int rangeLog2 = nextRangeLog2 - (BitUtils.IsPowerOfTwo64(range) ? 1 : 0);
int rangeLog2 = nextRangeLog2 - (BitOperations.IsPow2(range) ? 1 : 0);
int parts = rangeLog2 > 32 ? 2 : 1;
int bitsPerPart = rangeLog2 / parts;

View File

@ -1,6 +1,7 @@
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Kernel.Common;
using System.Diagnostics;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Kernel.Memory
{
@ -259,11 +260,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (backwards)
{
index = (index * 64 + 63) - BitUtils.CountLeadingZeros64(mask);
index = (index * 64 + 63) - BitOperations.LeadingZeroCount((ulong)mask);
}
else
{
index = index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(mask));
index = index * 64 + BitOperations.LeadingZeroCount((ulong)BitUtils.ReverseBits64(mask));
}
}
@ -312,11 +313,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (backwards)
{
index = index * 64 + BitUtils.CountLeadingZeros64(BitUtils.ReverseBits64(mask));
index = index * 64 + BitOperations.LeadingZeroCount((ulong)BitUtils.ReverseBits64(mask));
}
else
{
index = (index * 64 + 63) - BitUtils.CountLeadingZeros64(mask);
index = (index * 64 + 63) - BitOperations.LeadingZeroCount((ulong)mask);
}
}

View File

@ -1,5 +1,6 @@
using Ryujinx.Common;
using System;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
@ -32,7 +33,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
int mask = _idMasks[index];
int firstFreeBit = BitUtils.CountLeadingZeros32((mask + 1) & ~mask);
int firstFreeBit = BitOperations.LeadingZeroCount((uint)((mask + 1) & ~mask));
if (firstFreeBit < 32)
{

View File

@ -3,6 +3,7 @@ using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading;
using System;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
@ -130,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.Success;
}
int codeMask = 1 << (32 - BitUtils.CountLeadingZeros32(code + 1));
int codeMask = 1 << (32 - BitOperations.LeadingZeroCount((uint)code + 1));
// Check if the property was already set.
if (((mask0 & codeMask) & 0x1e008) != 0)

View File

@ -459,11 +459,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{
if (argValues != null)
{
Logger.Debug?.Print(LogClass.KernelSvc, string.Format(formatOrSvcName, argValues));
Logger.Trace?.Print(LogClass.KernelSvc, string.Format(formatOrSvcName, argValues));
}
else
{
Logger.Debug?.Print(LogClass.KernelSvc, formatOrSvcName);
Logger.Trace?.Print(LogClass.KernelSvc, formatOrSvcName);
}
}
@ -479,7 +479,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
}
else
{
Logger.Debug?.Print(LogClass.KernelSvc, $"{svcName} returned result {result}.");
Logger.Trace?.Print(LogClass.KernelSvc, $"{svcName} returned result {result}.");
}
}
}

View File

@ -15,12 +15,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
// GetAppletResourceUserId() -> nn::applet::AppletResourceUserId
public ResultCode GetAppletResourceUserId(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceAm);
long appletResourceUserId = context.Device.System.AppletState.AppletResourceUserIds.Add(_pid);
context.ResponseData.Write(appletResourceUserId);
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { appletResourceUserId });
return ResultCode.Success;
}

View File

@ -24,6 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
private bool _vibrationPermitted;
private bool _usbFullKeyControllerEnabled;
private bool _isFirmwareUpdateAvailableForSixAxisSensor;
private bool _isSixAxisSensorUnalteredPassthroughEnabled;
private HidNpadJoyAssignmentMode _npadJoyAssignmentMode;
private HidNpadHandheldActivationMode _npadHandheldActivationMode;
@ -335,7 +336,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// StartSixAxisSensor(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode StartSixAxisSensor(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
@ -347,7 +349,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// StopSixAxisSensor(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode StopSixAxisSensor(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
@ -359,7 +362,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// IsSixAxisSensorFusionEnabled(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> bool IsEnabled
public ResultCode IsSixAxisSensorFusionEnabled(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_sixAxisSensorFusionEnabled);
@ -373,9 +377,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// EnableSixAxisSensorFusion(bool Enabled, nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode EnableSixAxisSensorFusion(ServiceCtx context)
{
_sixAxisSensorFusionEnabled = context.RequestData.ReadBoolean();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
_sixAxisSensorFusionEnabled = context.RequestData.ReadUInt32() != 0;
int sixAxisSensorHandle = context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _sixAxisSensorFusionEnabled });
@ -386,7 +390,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetSixAxisSensorFusionParameters(nn::hid::SixAxisSensorHandle, float RevisePower, float ReviseRange, nn::applet::AppletResourceUserId)
public ResultCode SetSixAxisSensorFusionParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
_sensorFusionParams = new HidSensorFusionParameters
{
@ -405,7 +410,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// GetSixAxisSensorFusionParameters(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> float RevisePower, float ReviseRange)
public ResultCode GetSixAxisSensorFusionParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_sensorFusionParams.RevisePower);
@ -420,7 +426,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// ResetSixAxisSensorFusionParameters(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode ResetSixAxisSensorFusionParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
_sensorFusionParams.RevisePower = 0;
@ -436,6 +443,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
public ResultCode SetAccelerometerParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
_accelerometerParams = new HidAccelerometerParameters
{
@ -454,7 +462,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// GetAccelerometerParameters(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> float X, float Y
public ResultCode GetAccelerometerParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_accelerometerParams.X);
@ -469,7 +478,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// ResetAccelerometerParameters(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode ResetAccelerometerParameters(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
_accelerometerParams.X = 0;
@ -484,9 +494,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetAccelerometerPlayMode(nn::hid::SixAxisSensorHandle, uint PlayMode, nn::applet::AppletResourceUserId)
public ResultCode SetAccelerometerPlayMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
_accelerometerPlayMode = context.RequestData.ReadUInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
_accelerometerPlayMode = context.RequestData.ReadUInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _accelerometerPlayMode });
@ -497,7 +508,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// GetAccelerometerPlayMode(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> uint PlayMode
public ResultCode GetAccelerometerPlayMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_accelerometerPlayMode);
@ -511,7 +523,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// ResetAccelerometerPlayMode(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode ResetAccelerometerPlayMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
_accelerometerPlayMode = 0;
@ -525,9 +538,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// SetGyroscopeZeroDriftMode(nn::hid::SixAxisSensorHandle, uint GyroscopeZeroDriftMode, nn::applet::AppletResourceUserId)
public ResultCode SetGyroscopeZeroDriftMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
_gyroscopeZeroDriftMode = (HidGyroscopeZeroDriftMode)context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
_gyroscopeZeroDriftMode = (HidGyroscopeZeroDriftMode)context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _gyroscopeZeroDriftMode });
@ -538,7 +551,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// GetGyroscopeZeroDriftMode(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle) -> int GyroscopeZeroDriftMode
public ResultCode GetGyroscopeZeroDriftMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write((int)_gyroscopeZeroDriftMode);
@ -552,7 +566,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// ResetGyroscopeZeroDriftMode(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
public ResultCode ResetGyroscopeZeroDriftMode(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
_gyroscopeZeroDriftMode = HidGyroscopeZeroDriftMode.Standard;
@ -566,7 +581,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// IsSixAxisSensorAtRest(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> bool IsAsRest
public ResultCode IsSixAxisSensorAtRest(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
bool isAtRest = true;
@ -582,8 +598,8 @@ namespace Ryujinx.HLE.HOS.Services.Hid
// IsFirmwareUpdateAvailableForSixAxisSensor(nn::hid::AppletResourceUserId, nn::hid::SixAxisSensorHandle, pid) -> bool UpdateAvailable
public ResultCode IsFirmwareUpdateAvailableForSixAxisSensor(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4;
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_isFirmwareUpdateAvailableForSixAxisSensor);
@ -593,6 +609,64 @@ namespace Ryujinx.HLE.HOS.Services.Hid
return ResultCode.Success;
}
[CommandHipc(84)] // 13.0.0+
// EnableSixAxisSensorUnalteredPassthrough(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle, u8 enabled)
public ResultCode EnableSixAxisSensorUnalteredPassthrough(ServiceCtx context)
{
_isSixAxisSensorUnalteredPassthroughEnabled = context.RequestData.ReadUInt32() != 0;
int sixAxisSensorHandle = context.RequestData.ReadInt32();
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _isSixAxisSensorUnalteredPassthroughEnabled });
return ResultCode.Success;
}
[CommandHipc(85)] // 13.0.0+
// IsSixAxisSensorUnalteredPassthroughEnabled(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle) -> u8 enabled
public ResultCode IsSixAxisSensorUnalteredPassthroughEnabled(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write(_isSixAxisSensorUnalteredPassthroughEnabled);
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
return ResultCode.Success;
}
[CommandHipc(87)] // 13.0.0+
// LoadSixAxisSensorCalibrationParameter(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle, u64 unknown)
public ResultCode LoadSixAxisSensorCalibrationParameter(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
// TODO: CalibrationParameter have to be determined.
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
return ResultCode.Success;
}
[CommandHipc(88)] // 13.0.0+
// GetSixAxisSensorIcInformation(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle) -> u64 unknown
public ResultCode GetSixAxisSensorIcInformation(ServiceCtx context)
{
int sixAxisSensorHandle = context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
// TODO: IcInformation have to be determined.
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
return ResultCode.Success;
}
[CommandHipc(91)]
// ActivateGesture(nn::applet::AppletResourceUserId, int Unknown0)
public ResultCode ActivateGesture(ServiceCtx context)
@ -606,16 +680,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid
}
[CommandHipc(100)]
// SetSupportedNpadStyleSet(nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag)
// SetSupportedNpadStyleSet(pid, nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag)
public ResultCode SetSupportedNpadStyleSet(ServiceCtx context)
{
ulong pid = context.Request.HandleDesc.PId;
ControllerType type = (ControllerType)context.RequestData.ReadInt32();
context.RequestData.BaseStream.Position += 4; // Padding
long appletResourceUserId = context.RequestData.ReadInt64();
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
appletResourceUserId,
type
});
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { pid, appletResourceUserId, type });
context.Device.Hid.Npads.SupportedStyleSets = type;
@ -623,17 +696,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid
}
[CommandHipc(101)]
// GetSupportedNpadStyleSet(nn::applet::AppletResourceUserId) -> uint nn::hid::NpadStyleTag
// GetSupportedNpadStyleSet(pid, nn::applet::AppletResourceUserId) -> uint nn::hid::NpadStyleTag
public ResultCode GetSupportedNpadStyleSet(ServiceCtx context)
{
long appletResourceUserId = context.RequestData.ReadInt64();
ulong pid = context.Request.HandleDesc.PId;
long appletResourceUserId = context.RequestData.ReadInt64();
context.ResponseData.Write((int)context.Device.Hid.Npads.SupportedStyleSets);
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
appletResourceUserId,
context.Device.Hid.Npads.SupportedStyleSets
});
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, context.Device.Hid.Npads.SupportedStyleSets });
return ResultCode.Success;
}
@ -658,7 +729,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
}
}
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"{supportedPlayerIds.Length} " + string.Join(",", supportedPlayerIds.ToArray()));
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"{supportedPlayerIds.Length} Players: " + string.Join(",", supportedPlayerIds.ToArray()));
return ResultCode.Success;
}

View File

@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services
if (serviceExists)
{
Logger.Debug?.Print(LogClass.KernelIpc, $"{service.GetType().Name}: {processRequest.Name}");
Logger.Trace?.Print(LogClass.KernelIpc, $"{service.GetType().Name}: {processRequest.Name}");
result = (ResultCode)processRequest.Invoke(service, new object[] { context });
}

View File

@ -0,0 +1,63 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Services.Account.Acc;
namespace Ryujinx.HLE.HOS.Services.Mnpp
{
[Service("mnpp:app")] // 13.0.0+
class IServiceForApplication : IpcService
{
public IServiceForApplication(ServiceCtx context) { }
[CommandHipc(0)]
// Initialize(pid)
public ResultCode Initialize(ServiceCtx context)
{
// Pid placeholder
context.RequestData.ReadInt64();
ulong pid = context.Request.HandleDesc.PId;
// TODO: Service calls set:sys GetPlatformRegion.
// If the result == 1 (China) it calls arp:r GetApplicationInstanceId and GetApplicationLaunchProperty to get the title id and store it internally.
// If not, it does nothing.
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { pid });
return ResultCode.Success;
}
[CommandHipc(1)]
// SendRawTelemetryData(nn::account::Uid user_id, buffer<bytes, 5> title_id)
public ResultCode SendRawTelemetryData(ServiceCtx context)
{
ulong titleIdInputPosition = context.Request.SendBuff[0].Position;
ulong titleIdInputSize = context.Request.SendBuff[0].Size;
UserId userId = context.RequestData.ReadStruct<UserId>();
// TODO: Service calls set:sys GetPlatformRegion.
// If the result != 1 (China) it returns ResultCode.Success.
if (userId.IsNull)
{
return ResultCode.InvalidArgument;
}
if (titleIdInputSize <= 64)
{
string titleId = MemoryHelper.ReadAsciiString(context.Memory, titleIdInputPosition, (long)titleIdInputSize);
// TODO: The service stores the titleId internally and seems proceed to some telemetry for China, which is not needed here.
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { userId, titleId });
return ResultCode.Success;
}
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { userId });
return ResultCode.InvalidBufferSize;
}
}
}

View File

@ -0,0 +1,13 @@
namespace Ryujinx.HLE.HOS.Services.Mnpp
{
enum ResultCode
{
ModuleId = 239,
ErrorCodeShift = 9,
Success = 0,
InvalidArgument = (100 << ErrorCodeShift) | ModuleId,
InvalidBufferSize = (101 << ErrorCodeShift) | ModuleId
}
}

View File

@ -77,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
arguments.Handle = CreateHandleFromMap(new NvMapHandle(size));
Logger.Info?.Print(LogClass.ServiceNv, $"Created map {arguments.Handle} with size 0x{size:x8}!");
Logger.Debug?.Print(LogClass.ServiceNv, $"Created map {arguments.Handle} with size 0x{size:x8}!");
return NvInternalResult.Success;
}
@ -265,7 +265,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{
DeleteMapWithHandle(pid, handle);
Logger.Info?.Print(LogClass.ServiceNv, $"Deleted map {handle}!");
Logger.Debug?.Print(LogClass.ServiceNv, $"Deleted map {handle}!");
return true;
}

View File

@ -135,6 +135,9 @@ namespace Ryujinx.Headless.SDL2
[Option("enable-error-logs", Required = false, Default = true, HelpText = "Enables printing error log messages.")]
public bool? LoggingEnableError { get; set; }
[Option("enable-trace-logs", Required = false, Default = false, HelpText = "Enables printing trace log messages.")]
public bool? LoggingEnableTrace { get; set; }
[Option("enable-guest-logs", Required = false, Default = true, HelpText = "Enables printing guest log messages.")]
public bool? LoggingEnableGuest { get; set; }

View File

@ -389,6 +389,7 @@ namespace Ryujinx.Headless.SDL2
Logger.SetEnable(LogLevel.Info, (bool)option.LoggingEnableInfo);
Logger.SetEnable(LogLevel.Warning, (bool)option.LoggingEnableWarning);
Logger.SetEnable(LogLevel.Error, (bool)option.LoggingEnableError);
Logger.SetEnable(LogLevel.Trace, (bool)option.LoggingEnableTrace);
Logger.SetEnable(LogLevel.Guest, (bool)option.LoggingEnableGuest);
Logger.SetEnable(LogLevel.AccessLog, (bool)option.LoggingEnableFsAccessLog);

View File

@ -41,8 +41,8 @@ namespace Ryujinx.Tests.Unicorn
public uint PC
{
get => GetRegister(Arm32Register.PC);
set => SetRegister(Arm32Register.PC, value);
get => GetRegister(Arm32Register.PC) & 0xfffffffeu;
set => SetRegister(Arm32Register.PC, (value & 0xfffffffeu) | (ThumbFlag ? 1u : 0u));
}
public uint CPSR
@ -87,6 +87,16 @@ namespace Ryujinx.Tests.Unicorn
set => CPSR = (CPSR & ~0x80000000u) | (value ? 0x80000000u : 0u);
}
public bool ThumbFlag
{
get => (CPSR & 0x00000020u) != 0;
set
{
CPSR = (CPSR & ~0x00000020u) | (value ? 0x00000020u : 0u);
SetRegister(Arm32Register.PC, (GetRegister(Arm32Register.PC) & 0xfffffffeu) | (value ? 1u : 0u));
}
}
public UnicornAArch32()
{
Interface.Checked(Interface.uc_open(UnicornArch.UC_ARCH_ARM, UnicornMode.UC_MODE_LITTLE_ENDIAN, out uc));

View File

@ -106,6 +106,18 @@ namespace Ryujinx.Tests.Cpu
_currAddress += 4;
}
protected void ThumbOpcode(ushort opcode)
{
_memory.Write(_currAddress, opcode);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite16(_currAddress, opcode);
}
_currAddress += 2;
}
protected ExecutionContext GetContext() => _context;
protected void SetContext(uint r0 = 0,
@ -126,7 +138,8 @@ namespace Ryujinx.Tests.Cpu
bool carry = false,
bool zero = false,
bool negative = false,
int fpscr = 0)
int fpscr = 0,
bool thumb = false)
{
_context.SetX(0, r0);
_context.SetX(1, r1);
@ -151,6 +164,8 @@ namespace Ryujinx.Tests.Cpu
SetFpscr((uint)fpscr);
_context.SetPstateFlag(PState.TFlag, thumb);
if (_unicornAvailable)
{
_unicornEmu.R[0] = r0;
@ -175,6 +190,8 @@ namespace Ryujinx.Tests.Cpu
_unicornEmu.NegativeFlag = negative;
_unicornEmu.Fpscr = fpscr;
_unicornEmu.ThumbFlag = thumb;
}
}
@ -218,6 +235,28 @@ namespace Ryujinx.Tests.Cpu
return GetContext();
}
protected ExecutionContext SingleThumbOpcode(ushort opcode,
uint r0 = 0,
uint r1 = 0,
uint r2 = 0,
uint r3 = 0,
uint sp = 0,
bool saturation = false,
bool overflow = false,
bool carry = false,
bool zero = false,
bool negative = false,
int fpscr = 0,
bool runUnicorn = true)
{
ThumbOpcode(opcode);
ThumbOpcode(0x4770); // BX LR
SetContext(r0, r1, r2, r3, sp, default, default, default, default, default, default, default, default, saturation, overflow, carry, zero, negative, fpscr, thumb: true);
ExecuteOpcodes(runUnicorn);
return GetContext();
}
protected void SetWorkingMemory(uint offset, byte[] data)
{
_memory.Write(DataBaseAddress + offset, data);

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@ namespace Ryujinx.Configuration
/// <summary>
/// The current version of the file format
/// </summary>
public const int CurrentVersion = 35;
public const int CurrentVersion = 36;
/// <summary>
/// Version of the configuration file format
@ -81,6 +81,11 @@ namespace Ryujinx.Configuration
/// </summary>
public bool LoggingEnableError { get; set; }
/// <summary>
/// Enables printing trace log messages
/// </summary>
public bool LoggingEnableTrace { get; set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>

View File

@ -129,6 +129,11 @@ namespace Ryujinx.Configuration
/// </summary>
public ReactiveObject<bool> EnableError { get; private set; }
/// <summary>
/// Enables printing trace log messages
/// </summary>
public ReactiveObject<bool> EnableTrace { get; private set; }
/// <summary>
/// Enables printing guest log messages
/// </summary>
@ -161,6 +166,7 @@ namespace Ryujinx.Configuration
EnableInfo = new ReactiveObject<bool>();
EnableWarn = new ReactiveObject<bool>();
EnableError = new ReactiveObject<bool>();
EnableTrace = new ReactiveObject<bool>();
EnableGuest = new ReactiveObject<bool>();
EnableFsAccessLog = new ReactiveObject<bool>();
FilteredClasses = new ReactiveObject<LogClass[]>();
@ -455,6 +461,7 @@ namespace Ryujinx.Configuration
LoggingEnableInfo = Logger.EnableInfo,
LoggingEnableWarn = Logger.EnableWarn,
LoggingEnableError = Logger.EnableError,
LoggingEnableTrace = Logger.EnableTrace,
LoggingEnableGuest = Logger.EnableGuest,
LoggingEnableFsAccessLog = Logger.EnableFsAccessLog,
LoggingFilteredClasses = Logger.FilteredClasses,
@ -526,6 +533,7 @@ namespace Ryujinx.Configuration
Logger.EnableInfo.Value = true;
Logger.EnableWarn.Value = true;
Logger.EnableError.Value = true;
Logger.EnableTrace.Value = false;
Logger.EnableGuest.Value = true;
Logger.EnableFsAccessLog.Value = false;
Logger.FilteredClasses.Value = Array.Empty<LogClass>();
@ -990,6 +998,15 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 36)
{
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
configurationFileFormat.LoggingEnableTrace = false;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
@ -1003,6 +1020,7 @@ namespace Ryujinx.Configuration
Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;

View File

@ -13,6 +13,7 @@ namespace Ryujinx.Configuration
ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo;
ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning;
ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError;
ConfigurationState.Instance.Logger.EnableTrace.Event += ReloadEnableTrace;
ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest;
ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog;
ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses;
@ -44,6 +45,11 @@ namespace Ryujinx.Configuration
Logger.SetEnable(LogLevel.Error, e.NewValue);
}
private static void ReloadEnableTrace(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Trace, e.NewValue);
}
private static void ReloadEnableGuest(object sender, ReactiveEventArgs<bool> e)
{
Logger.SetEnable(LogLevel.Guest, e.NewValue);

View File

@ -638,18 +638,18 @@ namespace Ryujinx.Ui
[Conditional("RELEASE")]
public void PerformanceCheck()
{
if (ConfigurationState.Instance.Logger.EnableDebug.Value)
if (ConfigurationState.Instance.Logger.EnableTrace.Value)
{
MessageDialog debugWarningDialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, null)
{
Title = "Ryujinx - Warning",
Text = "You have debug logging enabled, which is designed to be used by developers only.",
SecondaryText = "For optimal performance, it's recommended to disable debug logging. Would you like to disable debug logging now?"
Text = "You have trace logging enabled, which is designed to be used by developers only.",
SecondaryText = "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?"
};
if (debugWarningDialog.Run() == (int)ResponseType.Yes)
{
ConfigurationState.Instance.Logger.EnableDebug.Value = false;
ConfigurationState.Instance.Logger.EnableTrace.Value = false;
SaveConfig();
}

View File

@ -35,6 +35,7 @@ namespace Ryujinx.Ui.Windows
private float _previousVolumeLevel;
#pragma warning disable CS0649, IDE0044
[GUI] CheckButton _traceLogToggle;
[GUI] CheckButton _errorLogToggle;
[GUI] CheckButton _warningLogToggle;
[GUI] CheckButton _infoLogToggle;
@ -141,6 +142,11 @@ namespace Ryujinx.Ui.Windows
};
// Setup Currents.
if (ConfigurationState.Instance.Logger.EnableTrace)
{
_traceLogToggle.Click();
}
if (ConfigurationState.Instance.Logger.EnableFileLog)
{
_fileLogToggle.Click();
@ -487,6 +493,7 @@ namespace Ryujinx.Ui.Windows
}
ConfigurationState.Instance.Logger.EnableError.Value = _errorLogToggle.Active;
ConfigurationState.Instance.Logger.EnableTrace.Value = _traceLogToggle.Active;
ConfigurationState.Instance.Logger.EnableWarn.Value = _warningLogToggle.Active;
ConfigurationState.Instance.Logger.EnableInfo.Value = _infoLogToggle.Active;
ConfigurationState.Instance.Logger.EnableStub.Value = _stubLogToggle.Active;

View File

@ -2572,6 +2572,24 @@
<property name="position">21</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="_traceLogToggle">
<property name="label" translatable="yes">Enable Trace Logs</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="tooltip-text" translatable="yes">Enables printing trace log messages</property>
<property name="halign">start</property>
<property name="margin-top">5</property>
<property name="margin-bottom">5</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">22</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>