Add breakpoint intrinsic in oscar.h

This commit is contained in:
drmortalwombat 2024-08-09 18:05:44 +02:00
parent 932c7ec222
commit 8a6e3eb924
11 changed files with 83 additions and 5 deletions

View File

@ -4739,9 +4739,14 @@ __asm inp_free
#pragma bytecode(BC_FREE, inp_free) #pragma bytecode(BC_FREE, inp_free)
__asm breakpoint
{
rts
}
#pragma runtime(malloc, malloc) #pragma runtime(malloc, malloc)
#pragma runtime(free, free) #pragma runtime(free, free)
#pragma runtime(breakpoint, breakpoint)
#if 0 #if 0

View File

@ -11,6 +11,13 @@ __native const char * oscar_expand_rle(char * dp, const char * sp);
// memory as buffer // memory as buffer
__native const char * oscar_expand_lzo_buf(char * dp, const char * sp); __native const char * oscar_expand_lzo_buf(char * dp, const char * sp);
// Write a breakpoint instruction into the .lbl file for vice. This
// intrinsic function will change the behaviour of the optimizer to ensure
// that the breakpoint is not move around into wild places.
void breakpoint(void);
#pragma intrinsic(breakpoint)
#pragma compile("oscar.c") #pragma compile("oscar.c")
#endif #endif

View File

@ -961,6 +961,7 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("malloc")); RegisterRuntime(loc, Ident::Unique("malloc"));
RegisterRuntime(loc, Ident::Unique("free")); RegisterRuntime(loc, Ident::Unique("free"));
RegisterRuntime(loc, Ident::Unique("breakpoint"));
} }
// Register extended byte code functions // Register extended byte code functions

View File

@ -1037,7 +1037,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
ex->mDecType = mDecType; ex->mDecType = mDecType;
return ex; return ex;
} }
else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight->mType == EX_CONSTANT) else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight && mRight->mType == EX_CONSTANT)
{ {
Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue; Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue;
const Ident* iname = decf->mQualIdent; const Ident* iname = decf->mQualIdent;

View File

@ -1698,12 +1698,12 @@ void ValueSet::InsertValue(InterInstruction * ins)
static bool HasSideEffect(InterCode code) static bool HasSideEffect(InterCode code)
{ {
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH /* || code == IC_MALLOC || code == IC_FREE */; return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH || code == IC_BREAKPOINT;/* || code == IC_MALLOC || code == IC_FREE */;
} }
static bool IsObservable(InterCode code) static bool IsObservable(InterCode code)
{ {
return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_FILL || code == IC_MALLOC || code == IC_FREE; return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_FILL || code == IC_MALLOC || code == IC_FREE || code == IC_BREAKPOINT;
} }
static bool IsMoveable(InterCode code) static bool IsMoveable(InterCode code)
@ -5389,6 +5389,9 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc)
case IC_UNREACHABLE: case IC_UNREACHABLE:
fprintf(file, "UNREACHABLE"); fprintf(file, "UNREACHABLE");
break; break;
case IC_BREAKPOINT:
fprintf(file, "BREAKPOINT");
break;
} }
static char typechars[] = "NBCILFP"; static char typechars[] = "NBCILFP";

View File

@ -42,7 +42,8 @@ enum InterCode
IC_JUMPF, IC_JUMPF,
IC_SELECT, IC_SELECT,
IC_DISPATCH, IC_DISPATCH,
IC_UNREACHABLE IC_UNREACHABLE,
IC_BREAKPOINT
}; };
enum InterType enum InterType

View File

@ -3436,6 +3436,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
else if (!strcmp(iname->mString, "exp")) else if (!strcmp(iname->mString, "exp"))
{ {
} }
else if (!strcmp(iname->mString, "breakpoint"))
{
InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BREAKPOINT);
ins->mNumOperands = 0;
block->Append(ins);
return ExValue(TheVoidTypeDeclaration, 0);
}
else if (!strcmp(iname->mString, "malloc")) else if (!strcmp(iname->mString, "malloc"))
{ {
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, gotos, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, gotos, breakBlock, continueBlock, inlineMapper);

View File

@ -137,7 +137,7 @@ LinkerOverlay::~LinkerOverlay(void)
} }
Linker::Linker(Errors* errors) Linker::Linker(Errors* errors)
: mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr), mOverlays(nullptr), mCompilerOptions(COPT_DEFAULT) : mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr), mOverlays(nullptr), mBreakpoints(0), mCompilerOptions(COPT_DEFAULT)
{ {
for (int i = 0; i < 64; i++) for (int i = 0; i < 64; i++)
{ {
@ -850,6 +850,32 @@ void Linker::CopyObjects(bool inlays)
} }
} }
void Linker::CollectBreakpoints(void)
{
for (int i = 0; i < mReferences.Size(); i++)
{
LinkerReference* ref = mReferences[i];
if (ref->mFlags & LREF_BREAKPOINT)
{
LinkerObject* obj = ref->mObject;
if (obj->mFlags & LOBJF_REFERENCED)
{
if (obj->mRegion)
{
if (obj->mRegion->mCartridgeBanks)
{
}
else
{
mBreakpoints.Push(obj->mAddress + ref->mOffset);
}
}
}
}
}
}
void Linker::PatchReferences(bool inlays) void Linker::PatchReferences(bool inlays)
{ {
for (int i = 0; i < mReferences.Size(); i++) for (int i = 0; i < mReferences.Size(); i++)
@ -1119,6 +1145,7 @@ void Linker::Link(void)
CopyObjects(false); CopyObjects(false);
PatchReferences(false); PatchReferences(false);
CollectBreakpoints();
for (int i = 0; i < mObjects.Size(); i++) for (int i = 0; i < mObjects.Size(); i++)
{ {
@ -1866,6 +1893,11 @@ bool Linker::WriteLblFile(const char* filename)
} }
} }
for (int i = 0; i < mBreakpoints.Size(); i++)
{
fprintf(file, "break %04x\n", mBreakpoints[i]);
}
fclose(file); fclose(file);
return true; return true;

View File

@ -110,6 +110,7 @@ static const uint32 LREF_HIGHBYTE = 0x00000002;
static const uint32 LREF_TEMPORARY = 0x00000004; static const uint32 LREF_TEMPORARY = 0x00000004;
static const uint32 LREF_INBLOCK = 0x00000008; static const uint32 LREF_INBLOCK = 0x00000008;
static const uint32 LREF_LOWBYTE_OFFSET = 0x00000010; static const uint32 LREF_LOWBYTE_OFFSET = 0x00000010;
static const uint32 LREF_BREAKPOINT = 0x00000020;
class LinkerReference class LinkerReference
{ {
@ -292,6 +293,7 @@ public:
GrowingArray<LinkerSection*> mSections; GrowingArray<LinkerSection*> mSections;
GrowingArray<LinkerObject*> mObjects; GrowingArray<LinkerObject*> mObjects;
GrowingArray<LinkerOverlay*> mOverlays; GrowingArray<LinkerOverlay*> mOverlays;
GrowingArray<uint32> mBreakpoints;
uint8 mMemory[0x10000], mWorkspace[0x10000]; uint8 mMemory[0x10000], mWorkspace[0x10000];
uint8 mCartridge[64][0x10000]; uint8 mCartridge[64][0x10000];
@ -312,6 +314,7 @@ public:
void CopyObjects(bool inlays); void CopyObjects(bool inlays);
void PlaceObjects(bool retry); void PlaceObjects(bool retry);
void Link(void); void Link(void);
void CollectBreakpoints(void);
protected: protected:
NativeCodeDisassembler mNativeDisassembler; NativeCodeDisassembler mNativeDisassembler;
ByteCodeDisassembler mByteCodeDisassembler; ByteCodeDisassembler mByteCodeDisassembler;

View File

@ -4884,6 +4884,17 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
if (mType == ASMIT_BYTE) if (mType == ASMIT_BYTE)
block->PutByte(mAddress); block->PutByte(mAddress);
else if (mType == ASMIT_JSR && (mFlags & NCIF_BREAKPOINT))
{
LinkerReference rl;
rl.mOffset = block->mCode.Size();
rl.mRefObject = nullptr;
rl.mRefOffset = 0;
rl.mFlags = LREF_BREAKPOINT;
block->mRelocations.Push(rl);
}
else if (mType == ASMIT_JSR && mLinkerObject && (mLinkerObject->mFlags & LOBJF_INLINE)) else if (mType == ASMIT_JSR && mLinkerObject && (mLinkerObject->mFlags & LOBJF_INLINE))
{ {
int pos = block->mCode.Size(); int pos = block->mCode.Size();
@ -52564,6 +52575,11 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
case IC_FREE: case IC_FREE:
block->CallFree(iproc, ins, this); block->CallFree(iproc, ins, this);
break; break;
case IC_BREAKPOINT:
{
NativeCodeGenerator::Runtime& frt(mGenerator->ResolveRuntime(Ident::Unique("breakpoint")));
block->mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_LOWER | NCIF_UPPER | NCIF_VOLATILE | NCIF_BREAKPOINT));
} break;
case IC_LOAD_TEMPORARY: case IC_LOAD_TEMPORARY:
{ {

View File

@ -133,6 +133,8 @@ static const uint32 NCIF_USE_ZP_32_X = 0x00008000;
static const uint32 NICF_USE_ZP_ADDR = 0x00010000; static const uint32 NICF_USE_ZP_ADDR = 0x00010000;
static const uint32 NICF_USE_WORKREGS = 0x00020000; static const uint32 NICF_USE_WORKREGS = 0x00020000;
static const uint32 NCIF_BREAKPOINT = 0x00040000;
class NativeCodeInstruction class NativeCodeInstruction
{ {
public: public: