summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/BackEnd/PowerPC/InlineAssembler/FuncLevelAsmPPC.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.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.c393
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) {
+}