summaryrefslogtreecommitdiff
path: root/compiler_and_linker/unsorted/StackFrame.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/unsorted/StackFrame.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/unsorted/StackFrame.c')
-rw-r--r--compiler_and_linker/unsorted/StackFrame.c1252
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;
- }
-}