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/unsorted/StackFrame.c | |
parent | fc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff) | |
download | MWCC-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/unsorted/StackFrame.c')
-rw-r--r-- | compiler_and_linker/unsorted/StackFrame.c | 1252 |
1 files changed, 0 insertions, 1252 deletions
diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c deleted file mode 100644 index 6fa4524..0000000 --- a/compiler_and_linker/unsorted/StackFrame.c +++ /dev/null @@ -1,1252 +0,0 @@ -#include "compiler/StackFrame.h" -#include "compiler/CError.h" -#include "compiler/CFunc.h" -#include "compiler/CMachine.h" -#include "compiler/CParser.h" -#include "compiler/CodeGen.h" -#include "compiler/CompilerTools.h" -#include "compiler/PCode.h" -#include "compiler/PCodeInfo.h" -#include "compiler/PCodeUtilities.h" -#include "compiler/RegisterInfo.h" -#include "compiler/objects.h" -#include "compiler/types.h" - -#define ALIGN(thing, alignment) ( ~((alignment) - 1) & ((thing) + (alignment) - 1) ) -#define ALIGN_REMAINDER(thing, alignment) ( ALIGN(thing, alignment) - (thing) ) - -Boolean requires_frame; -Boolean makes_call; -Boolean uses_globals; -Boolean dynamic_stack; -Boolean large_stack; -static SInt32 out_param_alignment; -static SInt32 in_parameter_size; -static SInt32 in_param_alignment; -static SInt32 frame_alignment; -static SInt32 alloca_alignment; -static SInt32 linkage_area_size; -static SInt32 parameter_area_size; -static SInt32 parameter_area_size_estimate; -static SInt32 local_data_size; -static SInt32 local_data_limit; -static SInt32 large_data_near_size; -static SInt32 large_data_far_size; -static ObjectList *local_objects[ObjClassMax]; -static ObjectList *local_objects_tail[ObjClassMax]; -static SInt32 non_volatile_save_offset[RegClassMax]; -static SInt32 VRSAVE_save_offset; -static SInt32 LR_save_offset; -static SInt32 nonvolatile_save_size; -static UInt32 vrsave_mask; -static SInt32 frame_size; -static SInt32 frame_size_estimate; -static SInt32 genuine_frame_size; -static Object *dummylocal; -static Boolean dynamic_align_stack; -static Boolean has_varargs; -static Boolean compressing_data_area; -static PCode *setup_caller_sp; -static PCode *align_instr1; -static PCode *align_instr2; -static short vrsave_register; -static PCode *loadvrsave; -static PCode *storevrsave; -Object *dummyvaparam; -void *dummyprofiler; - -// forward declarations -static void insert_local_object(UInt8 oclass, Object *obj); -static void compress_data_area(void); -static UInt32 align_bits(UInt32 value, UInt8 bitcount); -static Boolean use_helper_function(char rclass); -static Boolean need_link_register(void); -static void call_helper_function(char *name, char rclass, short effect); -static void save_nonvolatile_FPRs(int reg, SInt32 offset); -static void save_nonvolatile_VRs(int reg, SInt32 offset); -static void restore_nonvolatile_FPRs(int reg, SInt32 offset); -static void restore_nonvolatile_VRs(int reg, SInt32 offset); -static void save_nonvolatile_GPRs(int reg, SInt32 offset); -static void restore_nonvolatile_GPRs(int reg, SInt32 offset); -static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size); - -void init_stack_globals(Object *funcobj) { - RegClass rclass; - ObjClass oclass; - - requires_frame = 0; - makes_call = 0; - uses_globals = 0; - dynamic_stack = 0; - large_stack = 0; - vrsave_register = -1; - dynamic_align_stack = 0; - compressing_data_area = 0; - align_instr1 = NULL; - align_instr2 = NULL; - setup_caller_sp = NULL; - dummyvaparam = NULL; - loadvrsave = NULL; - storevrsave = NULL; - local_data_size = 0; - local_data_limit = 0x2000; - large_data_near_size = 0; - large_data_far_size = 0; - frame_size_estimate = 0; - in_parameter_size = 0; - parameter_area_size = 0; - parameter_area_size_estimate = 0; - frame_alignment = 8; - out_param_alignment = 8; - in_param_alignment = 8; - alloca_alignment = 0; - has_varargs = 0; - linkage_area_size = 0; - frame_size = 0; - genuine_frame_size = 0; - nonvolatile_save_size = -1; - VRSAVE_save_offset = -1; - LR_save_offset = -1; - - for (rclass = 0; rclass < RegClassMax; rclass++) - non_volatile_save_offset[rclass] = -1; - - dummyprofiler = NULL; - dummyvaparam = NULL; - dummylocal = NULL; - - for (oclass = 0; oclass < ObjClassMax; oclass++) { - local_objects[oclass] = NULL; - local_objects_tail[oclass] = NULL; - } -} - -void init_frame_sizes(Boolean has_varargs) { - ObjectList *scan; - Object *obj; - SInt32 r30; - SInt32 align; - SInt32 mask; - - r30 = in_parameter_size + parameter_area_size_estimate; - frame_size_estimate = r30 + 2484; - for (scan = locals; scan; scan = scan->next) { - obj = scan->object; - { - align = CMach_AllocationAlignment(obj->type, obj->qual) - 1; - mask = ~align; - } - frame_size_estimate = (frame_size_estimate + align) & mask; - frame_size_estimate += obj->type->size; - } - - if (frame_size_estimate > 0x8000) { - dynamic_stack = 1; - large_stack = 1; - requires_frame = 1; - } - - local_data_limit = 0x8000 - (r30 + 2484); - - if (dynamic_stack) { - requires_frame = 1; - dummylocal = galloc(sizeof(Object)); - memclrw(dummylocal, sizeof(Object)); - dummylocal->type = (Type *) &stvoid; - dummylocal->otype = OT_OBJECT; - dummylocal->name = GetHashNameNode("<dummy>"); - dummylocal->datatype = DLOCAL; - dummylocal->u.var.info = CodeGen_GetNewVarInfo(); - dummylocal->u.var.info->flags |= VarInfoFlag80; - dummylocal->u.var.info->noregister = 1; - } - - if (dynamic_stack) { - retain_register(NULL, RegClass_GPR, 31); - _FP_ = 31; - } else { - _FP_ = 1; - } -} - -void assign_local_memory(Object *obj) { - // some misassigned registers x.x - short align; - VarInfo *vi; - - align = CMach_AllocationAlignment(obj->type, obj->qual); - if (!compressing_data_area && (obj->u.var.info->flags & VarInfoFlag80)) - return; - - update_frame_align(align); - if (local_data_size + (ALIGN_REMAINDER(local_data_size, align) + ALIGN(obj->type->size, align)) < local_data_limit) { - local_data_size = ALIGN(local_data_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = local_data_size; - local_data_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass0, obj); - return; - } - if (compressing_data_area || obj->type->size <= 32) { - large_data_near_size = ALIGN(large_data_near_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = 0x8000 + large_data_near_size; - large_data_near_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass1, obj); - } else { - large_data_far_size = ALIGN(large_data_far_size, align); - vi = Registers_GetVarInfo(obj); - vi->flags &= ~VarInfoFlag2; - vi->flags |= VarInfoFlag80; - obj->u.var.uid = 0x10000 + large_data_far_size; - large_data_far_size += ALIGN(obj->type->size, align); - insert_local_object(ObjClass2, obj); - } -} - -void assign_locals_to_memory(ObjectList *first) { - ObjectList *list; - Object *obj; - SInt32 i; - - for (i = 1; i < 1024; i <<= 1) { - for (list = first; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) { - if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { - if (obj->type->size <= i) - assign_local_memory(obj); - } - } - } - } - - for (list = first; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) { - if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0) { - assign_local_memory(list->object); - } - } - - if (obj->type && IS_TYPE_ARRAY(obj->type) && IS_TYPE_VECTOR(TYPE_POINTER(obj->type)->target)) - has_altivec_arrays = 1; - } -} - -void compute_frame_sizes(void) { - SInt32 altivec_size; - SInt32 altivec_offset; - - CError_ASSERT(897, alloca_alignment == 0 || alloca_alignment == frame_alignment); - - update_asm_nonvolatile_registers(); - LR_save_offset = 8; - non_volatile_save_offset[RegClass_FPR] = -(used_nonvolatile_registers[RegClass_FPR] * 8); - non_volatile_save_offset[RegClass_GPR] = -(((15 - non_volatile_save_offset[RegClass_FPR]) & ~15) + used_nonvolatile_registers[RegClass_GPR] * 4); - nonvolatile_save_size = -non_volatile_save_offset[RegClass_GPR]; - non_volatile_save_offset[RegClass_CRFIELD] = 4; - VRSAVE_save_offset = -1; - non_volatile_save_offset[RegClass_VR] = -1; - - if (copts.altivec_model) { - if (vrsave_mask) { - VRSAVE_save_offset = non_volatile_save_offset[RegClass_GPR] - 4; - nonvolatile_save_size = nonvolatile_save_size + 4; - } - altivec_size = used_nonvolatile_registers[RegClass_VR] * 16; - if (altivec_size > 0) - nonvolatile_save_size = ALIGN(nonvolatile_save_size + altivec_size, frame_alignment); - } - - if (parameter_area_size) - requires_frame = 1; - - compress_data_area(); - local_data_size = ALIGN(local_data_size, frame_alignment); - nonvolatile_save_size = ALIGN(nonvolatile_save_size, frame_alignment); - if (!requires_frame && (local_data_size + nonvolatile_save_size) <= 224) { - CError_ASSERT(1005, !dynamic_align_stack); - linkage_area_size = 0; - frame_size = 0; - genuine_frame_size = local_data_size + nonvolatile_save_size; - } else { - requires_frame = 1; - if (parameter_area_size < 32) - parameter_area_size = 32; - parameter_area_size = ALIGN(parameter_area_size + 24, frame_alignment) - 24; - if (large_stack) { - CError_ASSERT(1019, !large_data_far_size); - large_data_near_size += parameter_area_size; - parameter_area_size = 0; - } - linkage_area_size = 24; - frame_size = nonvolatile_save_size + (altivec_offset = parameter_area_size + 24 + local_data_size); - if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) - non_volatile_save_offset[RegClass_VR] = altivec_offset; - frame_size += ALIGN_REMAINDER(frame_size, 16); - frame_size = ALIGN(frame_size, frame_alignment); - genuine_frame_size = frame_size; - } - if (!large_stack && frame_size > 0x7FFF) - CError_ErrorTerm(CErrorStr210); -} - -static void allocate_new_frame(int reg1, int reg2) { - if (dynamic_align_stack) { - CError_ASSERT(1116, reg1 != _CALLER_SP_); - emitpcode(PC_RLWINM, reg1, 1, 0, align_bits(frame_alignment, 1), 31); - if (frame_size > 0x7FFF) { - CError_FATAL(1122); - return; - } - - if (frame_size) - emitpcode(PC_SUBFIC, reg1, reg1, -frame_size); - else - emitpcode(PC_SUBFIC, reg1, reg1, -genuine_frame_size); - - if (reg2) - emitpcode(PC_MR, reg2, 1); - - emitpcode(PC_STWUX, 1, 1, reg1); - } else { - if (frame_size > 0x7FFF) - CError_FATAL(1153); - else - emitpcode(PC_STWU, 1, 1, 0, -frame_size); - - if (reg2) - emitpcode(PC_MR, reg2, 1); - } -} - -void generate_prologue(PCodeBlock *block, Boolean has_varargs) { - PCodeBlock *save_block; - Boolean needs_lr; - Statement *save_statement; - Statement stmt; - UInt32 vrsave_low; - UInt32 vrsave_high; - - save_block = pclastblock; - needs_lr = need_link_register(); - save_statement = current_statement; - stmt.sourceoffset = functionbodyoffset; - current_statement = &stmt; - pclastblock = block; - - if (setup_caller_sp && setup_caller_sp->block) { - if ( - setup_caller_sp->op == PC_MR && - setup_caller_sp->args[1].kind == PCOp_REGISTER && - setup_caller_sp->args[1].arg == RegClass_GPR && - setup_caller_sp->args[1].data.reg.reg == _FP_ - ) - CError_FATAL(1197); - - _CALLER_SP_ = setup_caller_sp->args[0].data.reg.reg; - deletepcode(setup_caller_sp); - setup_caller_sp = NULL; - } else if (_CALLER_SP_ != _FP_) { - _CALLER_SP_ = -1; - } - - if (align_instr1 && align_instr1->block) { - deletepcode(align_instr1); - align_instr1 = NULL; - } - - if (align_instr2 && align_instr2->block) { - deletepcode(align_instr2); - align_instr2 = NULL; - } - - if (loadvrsave && loadvrsave->block) { - deletepcode(loadvrsave); - loadvrsave = NULL; - } - - if (storevrsave && storevrsave->block) { - deletepcode(storevrsave); - storevrsave = NULL; - } - - if (needs_lr) - emitpcode(PC_MFLR, 0); - - if (used_nonvolatile_registers[RegClass_CRFIELD]) { - emitpcode(PC_MFCR, 12); - emitpcode(PC_STW, 12, 1, 0, non_volatile_save_offset[RegClass_CRFIELD]); - } - - if (used_nonvolatile_registers[RegClass_FPR]) - save_nonvolatile_FPRs(1, 0); - if (used_nonvolatile_registers[RegClass_GPR]) - save_nonvolatile_GPRs(1, 0); - if (needs_lr) - emitpcode(PC_STW, 0, 1, 0, 8); - - if (frame_size) { - if (vrsave_mask) { - emitpcode(PC_MFSPR, 0, 256); - emitpcode(PC_STW, 0, 1, 0, VRSAVE_save_offset); - vrsave_register = 0; - } - allocate_new_frame(12, (_CALLER_SP_ > 0 && _CALLER_SP_ != _FP_) ? _CALLER_SP_ : 0); - } else { - CError_ASSERT(1326, !dynamic_align_stack); - if (vrsave_mask) - emitpcode(PC_MFSPR, vrsave_register, 256); - } - - if (vrsave_mask) { - vrsave_high = vrsave_mask >> 16; - vrsave_low = vrsave_mask & 0xFFFF; - if (vrsave_mask == 0xFFFFFFFF) { - emitpcode(PC_LI, 0, -1); - } else { - if (vrsave_high) - emitpcode(PC_ORIS, 0, vrsave_register, vrsave_high); - if (vrsave_low) - emitpcode(PC_ORI, 0, 0, vrsave_low); - } - emitpcode(PC_MTSPR, 256, 0); - } - - if (used_nonvolatile_registers[RegClass_VR]) - save_nonvolatile_VRs(1, 0); - - if (dynamic_stack) - emitpcode(PC_MR, 31, 1); - - if (large_stack) - do_allocate_dynamic_stack_space(1, 11, 0, large_data_near_size); - - block->flags |= fIsProlog; - pclastblock = save_block; - current_statement = save_statement; -} - -void generate_epilogue(PCodeBlock *block, Boolean add_blr) { - PCodeBlock *save_block; - Boolean needs_lr; - Statement *save_statement; - Statement stmt; - - save_block = pclastblock; - needs_lr = need_link_register(); - save_statement = current_statement; - if (!save_statement) { - stmt.sourceoffset = current_linenumber; - current_statement = &stmt; - } - pclastblock = block; - - if (used_nonvolatile_registers[RegClass_VR]) - restore_nonvolatile_VRs(_FP_, 0); - - if (dynamic_align_stack) { - load_store_register(PC_LWZ, 1, 1, NULL, 0); - setpcodeflags(fSideEffects); - if (needs_lr) - load_store_register(PC_LWZ, 0, 1, 0, 8); - } else { - if (needs_lr) - load_store_register(PC_LWZ, 0, _FP_, 0, frame_size + 8); - if (frame_size > 0) { - if (dynamic_stack) { - load_store_register(PC_LWZ, 1, 1, 0, 0); - setpcodeflags(fSideEffects); - } else { - emitpcode(PC_ADDI, 1, 1, 0, frame_size); - setpcodeflags(fSideEffects); - } - } - } - - if (used_nonvolatile_registers[RegClass_CRFIELD]) { - load_store_register(PC_LWZ, 12, 1, NULL, non_volatile_save_offset[RegClass_CRFIELD]); - emitpcode(PC_MTCRF, 255, 12); - } - - if (vrsave_mask) { - if (!requires_frame) { - emitpcode(PC_MTSPR, 256, vrsave_register); - } else { - emitpcode(PC_LWZ, 11, 1, 0, VRSAVE_save_offset); - emitpcode(PC_MTSPR, 256, 11); - } - } - - if (used_nonvolatile_registers[RegClass_FPR]) - restore_nonvolatile_FPRs(1, 0); - if (needs_lr && !use_helper_function(RegClass_GPR)) - emitpcode(PC_MTLR, 0); - - if (used_nonvolatile_registers[RegClass_GPR]) - restore_nonvolatile_GPRs(1, 0); - if (needs_lr && use_helper_function(RegClass_GPR)) - emitpcode(PC_MTLR, 0); - - if (add_blr) { - emitpcode(PC_BLR); - setpcodeflags(fIsVolatile); - } - - block->flags |= fIsEpilogue; - pclastblock = save_block; - current_statement = save_statement; -} - -static void load_base_offset(int dest_reg, int base_reg, SInt32 offset) { - if (offset) - emitpcode(PC_ADDI, dest_reg, base_reg, 0, offset); - else - emitpcode(PC_MR, dest_reg, base_reg); -} - -static void save_nonvolatile_FPRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_FPR]; - - if (!use_helper_function(RegClass_FPR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { - emitpcode(PC_STFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); - call_helper_function("__save_fpr_%d", RegClass_FPR, EffectRead); - } -} - -static void save_nonvolatile_VRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_VR]; - - if (!use_helper_function(RegClass_VR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { - emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); - emitpcode(PC_STVX, 32 - i, reg, 0); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); - call_helper_function("__savev%d", RegClass_VR, EffectRead); - } -} - -static void restore_nonvolatile_FPRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_FPR]; - - if (!use_helper_function(RegClass_FPR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_FPR]; i++) { - load_store_register(PC_LFD, 32 - i, reg, NULL, o + (used_nonvolatile_registers[RegClass_FPR] - i) * 8); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_FPR] * 8); - call_helper_function("__restore_fpr_%d", RegClass_FPR, EffectWrite); - } -} - -static void restore_nonvolatile_VRs(int reg, SInt32 offset) { - short i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_VR]; - - if (!use_helper_function(RegClass_VR)) { - for (i = 1; i <= used_nonvolatile_registers[RegClass_VR]; i++) { - emitpcode(PC_LI, 0, o + (used_nonvolatile_registers[RegClass_VR] - i) * 16); - setpcodeflags(fIsVolatile); - emitpcode(PC_LVX, 32 - i, reg, 0); - setpcodeflags(fIsVolatile); - } - } else { - load_base_offset(0, reg, o + used_nonvolatile_registers[RegClass_VR] * 16); - call_helper_function("__restv%d", RegClass_VR, EffectWrite); - } -} - -static void save_nonvolatile_GPRs(int reg, SInt32 offset) { - int i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_GPR]; - - if (!use_helper_function(RegClass_GPR)) { - if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { - emitpcode(PC_STMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); - } else { - for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { - emitpcode(PC_STW, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); - } - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); - call_helper_function("__savegpr_%d", RegClass_GPR, EffectRead); - } -} - -static void restore_nonvolatile_GPRs(int reg, SInt32 offset) { - int i; - SInt32 o; - - o = offset + non_volatile_save_offset[RegClass_GPR]; - - if (!use_helper_function(RegClass_GPR)) { - if (copts.use_lmw_stmw && ((used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && (used_nonvolatile_registers[RegClass_GPR] > 1)))) { - emitpcode(PC_LMW, used_nonvolatile_registers[RegClass_GPR] - 1, 32 - used_nonvolatile_registers[RegClass_GPR], reg, 0, o); - setpcodeflags(fIsVolatile); - } else { - for (i = 1; i <= used_nonvolatile_registers[RegClass_GPR]; i++) { - emitpcode(PC_LWZ, 32 - i, reg, 0, o + (used_nonvolatile_registers[RegClass_GPR] - i) * 4); - setpcodeflags(fIsVolatile); - } - } - } else { - load_base_offset(11, reg, o + used_nonvolatile_registers[RegClass_GPR] * 4); - call_helper_function("__restgpr_%d", RegClass_GPR, EffectWrite); - } -} - -static void do_allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { - load_store_register(PC_LWZ, reg2, 1, NULL, 0); - if (isConstantSize) { - size = ALIGN(size, frame_alignment); - if (size < 0x8000) { - emitpcode(PC_STWU, reg2, 1, 0, -size); - } else { - emitpcode(PC_LIS, reg1, 0, (short) HIGH_PART(-size)); - if (-size) - emitpcode(PC_ADDI, reg1, reg1, 0, LOW_PART(-size)); - emitpcode(PC_STWUX, reg2, 1, reg1); - setpcodeflags(fIsVolatile | fSideEffects); - } - } else { - emitpcode(PC_STWUX, reg2, 1, reg1); - setpcodeflags(fIsVolatile | fSideEffects); - } -} - -void allocate_dynamic_stack_space(Boolean isConstantSize, int reg1, int reg2, SInt32 size) { - if (copts.altivec_model) - update_frame_align(16); - do_allocate_dynamic_stack_space(isConstantSize, reg1, reg2, size); - add_immediate(reg1, 1, dummylocal, 0); -} - -#ifdef __MWERKS__ -#pragma options align=mac68k -#endif -typedef struct Traceback { - UInt8 x0; - UInt8 x1; - UInt8 x2; - UInt8 x3; - UInt8 x4; - UInt8 x5; - - UInt8 x6_0 : 2; - UInt8 x6_1 : 1; // set to 1 - UInt8 x6_2 : 5; - - UInt8 x7_0 : 1; - UInt8 x7_1 : 1; // set to 1 - UInt8 has_dynamic_stack : 1; // set to 1 if dynamic_stack - UInt8 x7_3 : 3; - UInt8 uses_CRs : 1; // set to 1 if CRs used - UInt8 needs_link_register : 1; // set to 1 if link register used - - UInt8 has_frame_size : 1; // set to 1 if frame_size is nonzero - UInt8 x8_1 : 1; // set to 0 - UInt8 used_FPRs : 6; // stores non-volatile FPRs used - - UInt8 x9_0 : 1; // set to 0 - UInt8 x9_1 : 1; // set to 1 if VRs or vrsave used - UInt8 used_GPRs : 6; // stores non-volatile GPRs used - - UInt8 xA; - UInt8 xB; - - SInt32 funcsize; - SInt16 namelen; - char name[0]; -} Traceback; - -typedef struct TracebackExtra { - UInt8 used_VRs : 6; - UInt8 has_vrsave_mask : 1; - UInt8 is_varargs : 1; - UInt8 vec_arg_count : 7; - UInt8 has_vrsave_mask_or_used_VRs : 1; -} TracebackExtra; -#ifdef __MWERKS__ -#pragma options align=reset -#endif - -char *generate_traceback(SInt32 funcsize, char *funcname, SInt32 *tbsize, Object *func) { - char *work; - short namelen; - Traceback *buf; - SInt32 bufsize; - - namelen = strlen(funcname); - bufsize = ALIGN(sizeof(Traceback) + namelen + (dynamic_stack ? 1 : 0) + ((used_nonvolatile_registers[RegClass_VR] || vrsave_mask) ? sizeof(TracebackExtra) : 0), 4); - buf = lalloc(bufsize); - memclrw(buf, bufsize); - - buf->x4 = 0; - buf->x5 = copts.cplusplus ? 9 : 0; - buf->x6_1 = 1; - buf->x7_1 = 1; - if (dynamic_stack) - buf->has_dynamic_stack = 1; - if (used_nonvolatile_registers[RegClass_CRFIELD]) - buf->uses_CRs = 1; - if (need_link_register()) - buf->needs_link_register = 1; - if (frame_size) - buf->has_frame_size = 1; - buf->used_FPRs = used_nonvolatile_registers[RegClass_FPR]; - buf->used_GPRs = used_nonvolatile_registers[RegClass_GPR]; - buf->x8_1 = 0; - buf->x9_0 = 0; - buf->x9_1 = (used_nonvolatile_registers[RegClass_VR] || vrsave_mask) != 0; - buf->funcsize = funcsize; - buf->namelen = namelen; - - work = buf->name; - strcpy(work, funcname); - work += namelen; - if (dynamic_stack) { - *(work++) = 31; - } - - if (vrsave_mask || used_nonvolatile_registers[RegClass_VR]) { - TracebackExtra *extra; - Boolean is_varargs; - int vec_count; - FuncArg *args, *scan; - Type *type; - - extra = (TracebackExtra *) work; - vec_count = 0; - args = TYPE_FUNC(func->type)->args; - scan = args; - while (scan && scan != &elipsis) - scan = scan->next; - is_varargs = scan == &elipsis; - while (args) { - if ((type = args->type) && IS_TYPE_VECTOR(type)) - vec_count++; - args = args->next; - } - extra->used_VRs = used_nonvolatile_registers[RegClass_VR]; - extra->has_vrsave_mask = vrsave_mask != 0; - extra->is_varargs = is_varargs; - extra->vec_arg_count = vec_count; - extra->has_vrsave_mask_or_used_VRs = vrsave_mask || used_nonvolatile_registers[RegClass_VR]; - } - - *tbsize = bufsize; - return (char *) buf; -} - -static SInt32 localsbase(void) { - SInt32 size = parameter_area_size; - if (frame_size || dynamic_align_stack) - size += linkage_area_size; - else - size -= genuine_frame_size; - return size; -} - -static SInt32 parametersbase(int flag) { - if (flag) - return 24; - - return frame_size ? (genuine_frame_size + 24) : 24; -} - -void check_dynamic_aligned_frame(void) { - PCode *pc; - - if (used_nonvolatile_registers[RegClass_VR]) { - update_frame_align(16); - requires_frame = 1; - } - - if (frame_alignment > in_param_alignment) { - dynamic_align_stack = 1; - requires_frame = 1; - CError_ASSERT(2091, !has_varargs || _CALLER_SP_ != -1); - CError_ASSERT(2096, _CALLER_SP_ != _FP_); - if (setup_caller_sp && setup_caller_sp->block) { - align_instr1 = makepcode(PC_RLWINM, 12, 1, 0, 5, 31); - insertpcodebefore(setup_caller_sp, align_instr1); - align_instr2 = makepcode(PC_STWUX, 1, 1, 12); - insertpcodeafter(setup_caller_sp, align_instr2); - } - } else { - dynamic_align_stack = 0; - if (setup_caller_sp && setup_caller_sp->block) { - pc = makepcode(PC_MR, _CALLER_SP_, _FP_); - insertpcodebefore(setup_caller_sp, pc); - deletepcode(setup_caller_sp); - setup_caller_sp = pc; - } - _CALLER_SP_ = _FP_; - } - - vrsave_mask = 0; - if (copts.altivec_model) { - vrsave_mask = colored_vrs_as_vrsave(pcbasicblocks); - if (!requires_frame && vrsave_mask) { - vrsave_register = 11; - loadvrsave = makepcode(PC_LWZ, 11, 1, 0, -4); - appendpcode(prologue, loadvrsave); - storevrsave = makepcode(PC_STW, 11, 1, 0, -4); - appendpcode(epilogue, storevrsave); - } - } -} - -void move_varargs_to_memory(void) { - short reg; - - has_varargs = 1; - dummyvaparam = galloc(sizeof(Object)); - memclrw(dummyvaparam, sizeof(Object)); - - dummyvaparam->type = TYPE(&stvoid); - dummyvaparam->otype = OT_OBJECT; - dummyvaparam->name = GetHashNameNode("<vaparam>"); - dummyvaparam->datatype = DLOCAL; - dummyvaparam->u.var.info = CodeGen_GetNewVarInfo(); - dummyvaparam->u.var.uid = 0; - dummyvaparam->u.var.info->noregister = 1; - Registers_GetVarInfo(dummyvaparam)->flags = (Registers_GetVarInfo(dummyvaparam)->flags & ~VarInfoFlag1) | VarInfoFlag1; - - for (reg = last_argument_register[RegClass_GPR] + 1; (int)reg <= 10; reg++) { - emitpcode(PC_STW, reg, local_base_register(dummyvaparam), dummyvaparam, (reg - 3) * 4); - setpcodeflags(fIsPtrOp | fIsArgInit); - } -} - -void assign_arguments_to_memory(Object *func, UInt8 mysteryFlag, Boolean hasVarargs) { - // almost matches except for the not/andc issue - SInt32 pos; - ObjectList *list; - Object *obj; - Type *type; - short reg; - SInt32 chk; - Boolean flag; - - pos = 0; - reg = 2; - - for (list = arguments; list; list = list->next) { - obj = list->object; - type = obj->type; - if (!IS_TYPE_VECTOR(type)) { - obj->datatype = DLOCAL; - obj->u.var.info = CodeGen_GetNewVarInfo(); - if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || - IS_TYPE_12BYTES_MEMBERPOINTER(type)) { - chk = CMach_ArgumentAlignment(type); - if (chk > 4) { - pos = ALIGN(pos, chk); - update_in_param_align(chk); - } - } - obj->u.var.uid = pos; - Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; - if (!copts.littleendian && (IS_TYPE_INT(obj->type) || IS_TYPE_ENUM(obj->type)) && obj->type->size < 4) - obj->u.var.uid += 4 - obj->type->size; - pos += type->size; - pos = ALIGN(pos, 4); - } else { - obj->u.var.info = CodeGen_GetNewVarInfo(); - obj->u.var.uid = 0; - obj->datatype = DLOCAL; - flag = 1; - if (reg <= 13) - flag = hasVarargs; - if (flag) { - pos = ALIGN(pos + 24, 16) - 24; - obj->u.var.uid = pos; - pos += 16; - update_in_param_align(16); - Registers_GetVarInfo(obj)->flags = (Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1) | VarInfoFlag1; - } else { - assign_local_memory(obj); - Registers_GetVarInfo(obj)->flags = Registers_GetVarInfo(obj)->flags & ~VarInfoFlag1; - } - reg++; - } - } - - in_parameter_size = (in_parameter_size < pos) ? pos : in_parameter_size; - CError_ASSERT(2408, !dummyvaparam); -} - -SInt32 set_out_param_displ(SInt32 a, Type *type, Boolean flag, SInt32 *outvar, SInt32 b) { - // does not match due to errant andc - SInt32 argAlign; - - if (!flag && !b) { - *outvar = 0; - return a; - } - - if (IS_TYPE_VECTOR(type)) { - update_out_param_align(16); - a = ALIGN(a + 16 + 24, 16) - 24; - } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) || IS_TYPE_12BYTES_MEMBERPOINTER(type)) { - argAlign = CMach_ArgumentAlignment(type); - if (argAlign > 4) { - a = ALIGN(a + 24, argAlign) - 24; - update_in_param_align(argAlign); - } - } - - *outvar = a; - a = ALIGN(a + b, 4); - return a; -} - -SInt32 out_param_displ_to_offset(SInt32 displ) { - return displ + 24; -} - -Boolean needs_frame(void) { - return (frame_size > 224) || requires_frame; -} - -void update_out_param_size(SInt32 size) { - if (size < 32) - size = 32; - if (parameter_area_size < size) - parameter_area_size = size; -} - -void estimate_out_param_size(SInt32 size) { - if (parameter_area_size_estimate < size) - parameter_area_size_estimate = size; -} - -void update_out_param_align(SInt32 align) { - if (out_param_alignment < align) - out_param_alignment = align; - update_frame_align(align); -} - -void update_in_param_align(SInt32 align) { - if (in_param_alignment < align) - in_param_alignment = align; -} - -void update_frame_align(SInt32 align) { - if (frame_alignment < align) - frame_alignment = align; -} - -SInt32 local_offset_32(Object *obj) { - short align; - SInt32 offset; - - if (obj->u.var.info->flags & VarInfoFlag1) - align = CMach_ArgumentAlignment(obj->type); - else - align = CMach_AllocationAlignment(obj->type, obj->qual); - - offset = obj->u.var.uid; - if (offset > 0x7FFF) - offset = 0x8000 - offset - ALIGN(obj->type->size, align); - - if (obj->u.var.info->flags & VarInfoFlag1) - return offset + parametersbase(local_base_register(obj) != _FP_); - else - return offset + localsbase(); -} - -SInt32 local_offset_lo(Object *obj, SInt32 offset) { - SInt32 combo = offset + local_offset_32(obj); - return LOW_PART(combo); - //return (SInt16) (offset + local_offset_32(obj)); -} - -SInt32 local_offset_ha(Object *obj, SInt32 offset) { - SInt32 combo = offset + local_offset_32(obj); - return HIGH_PART(combo); - //return (SInt16) ((combo >> 16) + ((combo & 0x8000) >> 15)); -} - -SInt32 local_offset_16(Object *obj) { - SInt32 offset32 = local_offset_32(obj); - SInt16 offset16 = (SInt16) offset32; - CError_ASSERT(2662, offset32 == offset16); - return offset16; -} - -Boolean local_is_16bit_offset(Object *obj) { - SInt32 offset32 = local_offset_32(obj); - SInt16 offset16 = (SInt16) offset32; - return offset32 == offset16; -} - -int local_base_register(Object *obj) { - PCode *pc; - - if (obj->u.var.info->flags & VarInfoFlag1) { - if (coloring && _CALLER_SP_ == -1) { - _CALLER_SP_ = used_virtual_registers[RegClass_GPR]++; - pc = makepcode(PC_LWZ, _CALLER_SP_, 1, 0, 0); - setup_caller_sp = pc; - appendpcode(prologue, pc); - } - return _CALLER_SP_; - } else { - return _FP_; - } -} - -static UInt32 align_bits(UInt32 value, UInt8 bitcount) { - UInt32 base = bitcount != 0; - switch (value) { - case 0x0002: return base + 30; - case 0x0004: return base + 29; - case 0x0008: return base + 28; - case 0x0010: return base + 27; - case 0x0020: return base + 26; - case 0x0040: return base + 25; - case 0x0080: return base + 24; - case 0x0100: return base + 23; - case 0x0200: return base + 22; - case 0x0400: return base + 21; - case 0x0800: return base + 20; - case 0x1000: return base + 19; - case 0x2000: return base + 18; - default: - CError_FATAL(2754); - return base + 27; - } -} - -Boolean is_large_frame(void) { - CError_ASSERT(2769, frame_size != -1); - return large_stack; -} - -void no_frame_for_asm(void) { - frame_size = 0; -} - -Boolean can_add_displ_to_local(Object *obj, SInt32 displ) { - if (obj->datatype != DLOCAL) - return 0; - - if (local_offset_32(obj) == (short) local_offset_32(obj)) - if ((displ + local_offset_32(obj)) == (short) (displ + local_offset_32(obj))) - return 1; - - return 0; -} - -SInt32 get_alloca_alignment(void) { - SInt32 align = frame_alignment; - if (copts.altivec_model) - align = ALIGN(align, 16); - - if (!alloca_alignment) - alloca_alignment = align; - else - CError_ASSERT(2825, alloca_alignment == align); - - return align_bits(align, 0); -} - -static Boolean use_helper_function(char rclass) { - if (copts.no_register_save_helpers) - return 0; - - switch (rclass) { - case RegClass_GPR: - if (copts.use_lmw_stmw) - return 0; - return (used_nonvolatile_registers[RegClass_GPR] > 4) || (copts.optimizesize && used_nonvolatile_registers[RegClass_GPR] > 2); - case RegClass_FPR: - return (used_nonvolatile_registers[RegClass_FPR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_FPR] > 2); - case RegClass_VR: - return (used_nonvolatile_registers[RegClass_VR] > 3) || (copts.optimizesize && used_nonvolatile_registers[RegClass_VR] > 2); - default: - CError_FATAL(2862); - return 0; - } -} - -static Boolean need_link_register(void) { - if (copts.codegen_pic && uses_globals) - return 1; - - if (makes_call) - return 1; - - return use_helper_function(RegClass_FPR) || use_helper_function(RegClass_GPR) || use_helper_function(RegClass_VR); -} - -static void call_helper_function(char *name, char rclass, short effect) { - char str[32]; - Object *func; - NameSpace *save_scope; - PCode *pc; - int extra_args; - PCodeArg *arg; - short i; - - extra_args = 1; - if (rclass == RegClass_VR) - extra_args = 2; - - sprintf(str, name, 32 - used_nonvolatile_registers[rclass]); - - save_scope = cscope_current; - cscope_current = cscope_root; - func = CParser_NewRTFunc(&stvoid, NULL, 2, 0); - cscope_current = save_scope; - - func->name = GetHashNameNodeExport(str); - - pc = makepcode(PC_BL, extra_args + used_nonvolatile_registers[rclass], func, 0); - for (i = 1, arg = &pc->args[1]; i <= used_nonvolatile_registers[rclass]; i++, arg++) { - arg->kind = PCOp_REGISTER; - arg->arg = rclass; - arg->data.reg.reg = n_real_registers[rclass] - i; - arg->data.reg.effect = effect; - } - - if (rclass == RegClass_VR) { - arg[1].kind = PCOp_REGISTER; - arg[1].arg = RegClass_GPR; - arg[1].data.reg.reg = 12; - arg[1].data.reg.effect = EffectWrite; - arg[2].kind = PCOp_REGISTER; - arg[2].arg = RegClass_GPR; - arg[2].data.reg.reg = 0; - arg[2].data.reg.effect = EffectRead; - } else { - arg[1].kind = PCOp_REGISTER; - arg[1].arg = RegClass_GPR; - arg[1].data.reg.reg = 11; - arg[1].data.reg.effect = EffectRead; - } - - appendpcode(pclastblock, pc); - setpcodeflags(fSideEffects); -} - -static SInt32 nearest_power_of_two(SInt32 n) { - SInt32 power = 1; - do { - power <<= 1; - } while (power && power < n); - - CError_ASSERT(2933, power != 0); - return power; -} - -static void compress_data_area(void) { - // doesn't quite match - SInt32 r0; - SInt32 r7; - ObjectList *list; - Object *obj; - PCodeBlock *block; - PCode *pc; - int i; - - compressing_data_area = 1; - - if (large_stack) { - r0 = 0; - } else { - r0 = parameter_area_size; - if (r0 < 32) - r0 = 32; - } - r7 = ALIGN(r0 + 24, frame_alignment) - 24; - local_data_limit = 0x8000 - ALIGN(24 + in_parameter_size + nonvolatile_save_size + r7, frame_alignment); - - if (local_objects_tail[ObjClass0]) { - if (local_objects[ObjClass1]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass1]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; - } - if (local_objects[ObjClass2]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - } else if (local_objects_tail[ObjClass1]) { - local_objects[ObjClass0] = local_objects[ObjClass1]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass1]; - if (local_objects[ObjClass2]) { - local_objects_tail[ObjClass0]->next = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - } else { - local_objects[ObjClass0] = local_objects[ObjClass2]; - local_objects_tail[ObjClass0] = local_objects_tail[ObjClass2]; - } - - for (list = local_objects[ObjClass0]; list; list = list->next) - Registers_GetVarInfo(list->object)->used = 0; - - for (block = pcbasicblocks; block; block = block->nextBlock) { - for (pc = block->firstPCode; pc; pc = pc->nextPCode) { - for (i = 0; i < pc->argCount; i++) { - if (pc->args[i].kind == PCOp_MEMORY && pc->args[i].data.mem.obj && pc->args[i].data.mem.obj->datatype == DLOCAL) - Registers_GetVarInfo(pc->args[i].data.mem.obj)->used = 1; - } - } - } - - local_data_size = 0; - large_data_near_size = 0; - large_data_far_size = 0; - - for (list = local_objects[ObjClass0]; list; list = list->next) { - obj = list->object; - if (Registers_GetVarInfo(obj)->used) - assign_local_memory(obj); - } -} - -static void insert_local_object(UInt8 oclass, Object *obj) { - ObjectList *list; - - if (!compressing_data_area) { - list = lalloc(sizeof(ObjectList)); - memclrw(list, sizeof(ObjectList)); - list->object = obj; - if (!local_objects[oclass]) - local_objects[oclass] = list; - if (local_objects_tail[oclass]) - local_objects_tail[oclass]->next = list; - local_objects_tail[oclass] = list; - } -} |