diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-26 11:30:47 +0000 |
commit | 094b96ca1df4a035b5f93c351f773306c0241f3f (patch) | |
tree | 95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-main.tar.gz MWCC-main.zip |
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c')
-rw-r--r-- | compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c new file mode 100644 index 0000000..340a54b --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c @@ -0,0 +1,393 @@ +#include "compiler/FuncLevelAsmPPC.h" +#include "compiler/CCompiler.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrepTokenizer.h" +#include "compiler/CodeGen.h" +#include "compiler/Coloring.h" +#include "compiler/CompilerTools.h" +#include "compiler/DumpIR.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/InlineAsmRegisters.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeAssembly.h" +#include "compiler/PCodeListing.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/PPCError.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/TOC.h" +#include "compiler/objects.h" + +static EntryPoint *entrypoints_head; +static EntryPoint **entrypoints_tail; + +void setup_assembly_argument(Object *obj, short reg) { + VarInfo *vi; + Type *type; + + vi = Registers_GetVarInfo(obj); + type = obj->type; + vi->used = 1; + + if (!requires_frame) { + if (is_register_object(obj)) { + if (!reg) + CError_Error(CErrorStr263, obj->name->name); + + if (TYPE_IS_8BYTES(type)) { + short regLo; + short regHi; + if (reg < 10) { + if (copts.littleendian) { + regLo = reg; + regHi = reg + 1; + } else { + regLo = reg + 1; + regHi = reg; + } + retain_GPR_pair(obj, regLo, regHi); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, regLo, obj); + } + } else if (IS_TYPE_FLOAT(type)) { + retain_register(obj, RegClass_FPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_FPR, reg, obj); + } else if (IS_TYPE_VECTOR(type)) { + retain_register(obj, RegClass_VR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_VR, reg, obj); + } else { + retain_register(obj, RegClass_GPR, reg); + InlineAsm_InsertRegister(obj->name->name, RegClass_GPR, reg, obj); + } + } + } else { + if (is_register_object(obj)) { + vi = Registers_GetVarInfo(obj); + if (!vi->reg) { + assign_register_by_type(obj); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, obj->name->name); + else + InlineAsm_InsertRegister(obj->name->name, vi->rclass, vi->reg, obj); + } + } + } +} + +void assign_local_addresses(void) { + VarInfo *vi; + ObjectList *list; + Object *object; + + for (list = locals; list; list = list->next) { + vi = CodeGen_GetNewVarInfo(); + list->object->u.var.info = vi; + list->object->flags |= OBJECT_USED; + vi->used = 1; + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (is_register_object(object)) { + vi = Registers_GetVarInfo(object); + if (!vi->reg) { + assign_register_by_type(object); + if (!(vi->flags & VarInfoFlag2)) + CError_Error(CErrorStr263, object->name->name); + else + InlineAsm_InsertRegister(object->name->name, vi->rclass, vi->reg, object); + } + } + } + + for (list = locals; list; list = list->next) { + object = list->object; + if (OBJECT_REG(object) == 0) + assign_local_memory(object); + } +} + +static void FuncAsm_PreScanDirectives(void) { + SInt32 directive; + Boolean save_eoltokens; + + in_assembler = 1; + save_eoltokens = cprep_eoltokens; + cprep_eoltokens = 1; + + if (setjmp(InlineAsm_assemblererror) == 0) { + while (tk == TK_IDENTIFIER && (directive = InlineAsm_IsDirective(AssemblerType_1))) { + InlineAsm_ProcessDirective(directive); + + if (tk == ';' || tk == TK_EOL) { + CPrep_TokenStreamFlush(); + tk = lex(); + } else { + InlineAsm_SyntaxError(CErrorStr113); + } + + if (directive == IADirective_FrAlloc) { + requires_frame = 1; + break; + } else if (directive == IADirective_NoFrAlloc) { + user_responsible_for_frame = 1; + break; + } + } + } + + in_assembler = 0; + cprep_eoltokens = save_eoltokens; +} + +static void FuncAsm_AddEntryPoint(Statement *stmt, PCodeBlock *block) { + EntryPoint *ep; + IAEntryPoint *ia_ep; + + ia_ep = (IAEntryPoint *) stmt->expr; + ep = lalloc(sizeof(EntryPoint)); + memclrw(ep, sizeof(EntryPoint)); + + ep->object = ia_ep->x8; + ep->block = block; + + *entrypoints_tail = ep; + entrypoints_tail = &ep->next; + + block->flags |= fPCBlockFlag8000; +} + +void Assembler(Object *func) { + PCodeBlock *block; + Statement *stmt; + Boolean flag17; + Boolean flag16; + char *name; + InlineAsm *ia; + Boolean save_unusedvar; + Boolean save_unusedarg; + + flag17 = 0; + flag16 = 0; + + init_endian(); + init_stack_globals(func); + memclrw(asm_alloc_flags, sizeof(asm_alloc_flags)); + fralloc_parameter_area_size = 0; + user_responsible_for_frame = 0; + assembledinstructions = 0; + + entrypoints_head = NULL; + entrypoints_tail = &entrypoints_head; + + stmt = curstmt; + + if (func && func->name) + PrintProgressFunction(func->name->name); + + CodeGen_InitialSanityCheck(); + + if (func->qual & Q_INLINE) + PPCError_Warning(PPCErrorStr173); + + CheckCLabels(); + + if (fatalerrors) + return; + + if (copts.filesyminfo) + CPrep_SetSourceFile(&cparser_fileoffset); + + sm_section = SECT_TEXT; + + initpcode(); + + pclabel(prologue = makepcblock(), makepclabel()); + pclabel(block = makepcblock(), makepclabel()); + pcbranch(prologue, block->labels); + + resetTOCvarinfo(); + InlineAsm_InitializePPC(); + FuncAsm_PreScanDirectives(); + + disable_optimizer = 1; + + init_registers(); + assign_arguments_to_memory(func, 0, 0); + init_frame_sizes(0); + + if (copts.debuglisting) + DumpIR(stmt, func); + + cprep_eoltokens = 1; + in_assembler = 1; + + save_unusedvar = copts.warn_unusedvar; + save_unusedarg = copts.warn_unusedarg; + copts.warn_unusedvar = 0; + copts.warn_unusedarg = 0; + + InlineAsm_ScanFunction('}'); + + expandTOCreferences(&stmt->next); + + if (!anyerrors && copts.debuglisting) + DumpIR(stmt, func); + + in_assembler = 0; + cprep_eoltokens = 0; + + name = CMangler_GetLinkName(func)->name; + func->flags |= OBJECT_DEFINED; + + if (fralloc_parameter_area_size) + update_out_param_size(fralloc_parameter_area_size); + if (!user_responsible_for_frame) + process_arguments(move_assigned_argument, 0); + + branch_label(makepclabel()); + assign_labels(stmt->next); + + copts.warn_unusedvar = save_unusedvar; + copts.warn_unusedarg = save_unusedarg; + + for (stmt = stmt->next; stmt; stmt = stmt->next) { + current_statement = stmt; + switch (stmt->type) { + case ST_ASM: + if ((ia = (InlineAsm *) stmt->expr)) { + if (ia->flags & IAFlag1) { + if (ia->opcode == IADirective_Entry) { + branch_label(makepclabel()); + FuncAsm_AddEntryPoint(stmt, pclastblock); + } else if (ia->opcode == IADirective_FrFree) { + if (flag16) + PPCError_Error(PPCErrorStr188); + else + flag16 = 1; + + asm_alloc_flags[3] = 1; + asm_alloc_flags[4] = 1; + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fIsEpilogue; + + CheckCLabels(); + if (fatalerrors) + return; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + colorinstructions(func); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + compute_frame_sizes(); + generate_prologue(prologue, 0); + epilogue = pclastblock; + generate_epilogue(epilogue, 0); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + + flag17 = 1; + } + } else { + branch_label(makepclabel()); + asm_alloc_flags[6] = 0; + asm_alloc_flags[7] = 0; + InlineAsm_TranslateIRtoPCode(stmt); + asm_alloc_flags[4] = 0; + } + } + break; + case ST_LABEL: + if (!stmt->label->pclabel->resolved) + branch_label(stmt->label->pclabel); + break; + default: + CError_FATAL(525); + } + } + + current_statement = NULL; + + if (fatalerrors) + return; + CheckCLabels(); + if (fatalerrors) + return; + + if (!flag17) { + branch_label(makepclabel()); + + epilogue = pclastblock; + pclastblock->flags |= fIsEpilogue; + + pccomputepredecessors(); + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] INITIAL CODE"); + + if (!asm_alloc_flags[1]) { + colorinstructions(func); + if (fatalerrors) + return; + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER REGISTER COLORING"); + } + + compute_frame_sizes(); + if (asm_alloc_flags[1]) + no_frame_for_asm(); + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1]) { + generate_prologue(prologue, 0); + generate_epilogue(epilogue, !asm_alloc_flags[6] && !asm_alloc_flags[7]); + } + + if (copts.debuglisting) + pclistblocks(name, "[FUNCTION-LEVEL ASM] AFTER PROLOGUE/EPILOGUE CREATION"); + } + + if (fatalerrors) + return; + + if (!asm_alloc_flags[1] && needs_frame()) { + if (asm_alloc_flags[3]) { + if (!asm_alloc_flags[5] || !asm_alloc_flags[6]) + PPCError_Warning(PPCErrorStr187, "blr"); + if (asm_alloc_flags[8]) + PPCError_Warning(PPCErrorStr186); + } else { + PPCError_Warning(PPCErrorStr185, "blr"); + } + } + + func->section = sm_section; + + if (copts.filesyminfo) + symdeclend = CPrep_GetFileOffsetInfo(&cparser_fileoffset); + + copts.peephole = 0; + if (pic_base_label) + pic_base_pcodelabel = pic_base_label->pclabel; + assemblefunction(func, entrypoints_head); + + if (copts.debuglisting) + pclistblocks(CMangler_GetLinkName(func)->name, "[FUNCTION-LEVEL ASM] FINAL CODE"); + + CFunc_WarnUnused(); +} + +void SetupAssembler(void) { +} + +void CleanupAssembler(void) { +} |