#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/uDump.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.little_endian) { 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_FLAGS_UNUSED; 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_0))) { InlineAsm_ProcessDirective(directive); if (tk == ';' || tk == TK_NEG7) { 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(173); CheckCLabels(); if (fatalerrors) return; if (copts.isGeneratingDebugInfo) 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_FLAGS_4; 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(188); else flag16 = 1; asm_alloc_flags[3] = 1; asm_alloc_flags[4] = 1; branch_label(makepclabel()); epilogue = pclastblock; pclastblock->flags |= fPCBlockFlag2; 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 |= fPCBlockFlag2; 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(187, "blr"); if (asm_alloc_flags[8]) PPCError_Warning(186); } else { PPCError_Warning(185, "blr"); } } func->section = sm_section; if (copts.isGeneratingDebugInfo) 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) { }