summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/CodeGenerator
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/CodeGenerator
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/CodeGenerator')
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c2437
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c857
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c642
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c5348
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c4894
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c1040
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c1613
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c536
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c345
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c2753
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c1252
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c792
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c518
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c2272
14 files changed, 25299 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c
new file mode 100644
index 0000000..d3bac77
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/CodeGen.c
@@ -0,0 +1,2437 @@
+#include "compiler/CodeGen.h"
+#include "compiler/CCompiler.h"
+#include "compiler/CDecl.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CMangler.h"
+#include "compiler/COptimizer.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/Coloring.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/DumpIR.h"
+#include "compiler/Exceptions.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/Intrinsics.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/GlobalOptimizer.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeAssembly.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeListing.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Peephole.h"
+#include "compiler/PPCError.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/Scheduler.h"
+#include "compiler/StackFrame.h"
+#include "compiler/Switch.h"
+#include "compiler/TOC.h"
+#include "compiler/ValueNumbering.h"
+#include "compiler/enode.h"
+#include "compiler/objc.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/tokens.h"
+#include "compiler/types.h"
+
+static Macro powcM;
+static Macro __powcM;
+static Macro ppc_cpu;
+static Macro profM;
+static Macro hostM;
+static Macro bendM;
+static Macro _ppc_M;
+static Macro longI;
+static Macro IEEED;
+Macro vecM;
+Macro altivecM;
+static Macro macM2;
+static Macro appleM;
+static Macro optM;
+static Macro alignM;
+static Macro _machM;
+static Macro archM;
+static Macro dynM;
+static Macro ppcM;
+Object *gFunction;
+static ObjectList *temps;
+CLabel *returnlabel;
+CLabel *cleanreturnlabel;
+Boolean needs_cleanup;
+Statement *current_statement;
+int has_catch_blocks;
+int disable_optimizer;
+SInt32 current_linenumber;
+Boolean has_altivec_arrays;
+short high_reg;
+short low_reg;
+short high_offset;
+short low_offset;
+short low_reg2;
+short high_reg2;
+PCodeLabel *pic_base_pcodelabel;
+Object *dyld_stub_binding_helper;
+Object *rt_cvt_fp2unsigned;
+Object *rt_profile_entry;
+Object *rt_profile_exit;
+Object *rt_div2i;
+Object *rt_div2u;
+Object *rt_mod2i;
+Object *rt_mod2u;
+Object *rt_shr2i;
+Object *rt_shr2u;
+Object *rt_shl2i;
+Object *rt_cvt_ull_dbl;
+Object *rt_cvt_sll_dbl;
+Object *rt_cvt_ull_flt;
+Object *rt_cvt_sll_flt;
+Object *rt_cvt_dbl_usll;
+static heaperror_t saveheaperror;
+
+enum {
+ GPRLimit = 10,
+ FPRLimit = 13,
+ VRLimit = 13
+};
+
+// forward decls
+static void CodeGen_heaperror(void);
+
+VarInfo *CodeGen_GetNewVarInfo(void) {
+ VarInfo *vi;
+
+ vi = lalloc(sizeof(VarInfo));
+ memclrw(vi, sizeof(VarInfo));
+
+ vi->deftoken = *CPrep_CurStreamElement();
+ vi->varnumber = localcount++;
+
+ return vi;
+}
+
+Object *maketemporary(Type *type) {
+ ObjectList *list;
+ Object *obj;
+
+ for (list = temps; list; list = list->next) {
+ obj = list->object;
+ if (obj->u.var.uid == 0 && obj->type == type) {
+ obj->u.var.uid = 1;
+ return obj;
+ }
+ }
+
+ obj = lalloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->access = ACCESSPUBLIC;
+ obj->datatype = DLOCAL;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->u.var.info = CodeGen_GetNewVarInfo();
+ obj->u.var.uid = 1;
+
+ list = lalloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->next = temps;
+ list->object = obj;
+ temps = list;
+
+ return obj;
+}
+
+static void free_temporaries(void) {
+ ObjectList *list;
+
+ for (list = temps; list; list = list->next)
+ list->object->u.var.uid = 0;
+}
+
+static void allocate_temporaries(void) {
+ ObjectList *list;
+
+ for (list = temps; list; list = list->next)
+ assign_local_memory(list->object);
+}
+
+void process_arguments(ArgumentProcessor func, Boolean flag) {
+ short gpr = 3;
+ short fpr = 1;
+ short vr = 2;
+ Type *type;
+ ObjectList *list;
+
+ for (list = arguments; list; list = list->next) {
+ type = list->object->type;
+ if (IS_TYPE_FLOAT(type)) {
+ func(list->object, (fpr <= FPRLimit) ? fpr : 0);
+ fpr++;
+ if (type->size == 4)
+ gpr++;
+ else
+ gpr += 2;
+ } else if (IS_TYPE_VECTOR(type)) {
+ func(list->object, (vr <= VRLimit) ? vr : 0);
+ vr++;
+ if (flag) {
+ if ((vr - 1) == 2)
+ gpr = 9;
+ else if ((vr - 1) > 2)
+ gpr = 11;
+ }
+ } else {
+ func(list->object, (gpr <= GPRLimit) ? gpr : 0);
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (type->size <= 4)
+ gpr += 1;
+ else
+ gpr += 2;
+ } else {
+ gpr += (type->size >> 2);
+ if (type->size & 3)
+ gpr++;
+ }
+ }
+ }
+
+ last_argument_register[RegClass_GPR] = gpr - 1;
+ last_argument_register[RegClass_FPR] = fpr - 1;
+ last_argument_register[RegClass_VR] = vr - 1;
+ if (flag)
+ move_varargs_to_memory();
+}
+
+static void retain_argument_register(Object *obj, short reg) {
+ VarInfo *vi = Registers_GetVarInfo(obj);
+ Type *type = obj->type;
+
+ if (reg && !vi->noregister && vi->used) {
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (type->size <= 4) {
+ retain_register(obj, RegClass_GPR, reg);
+ } else if (reg < GPRLimit) {
+ if (copts.littleendian)
+ retain_GPR_pair(obj, reg, reg + 1);
+ else
+ retain_GPR_pair(obj, reg + 1, reg);
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ retain_register(obj, RegClass_FPR, reg);
+ } else if (IS_TYPE_VECTOR(type)) {
+ retain_register(obj, RegClass_VR, reg);
+ }
+ }
+}
+
+static void allocate_local_vregs(void) {
+ ObjectList *list;
+ Object *obj;
+ VarInfo *vi;
+
+ if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) {
+ if (assignable_registers[RegClass_GPR]) {
+ vi = pic_base.u.var.info;
+ vi->reg = 0;
+ assign_register_by_type(&pic_base);
+ pic_base_reg = vi->reg;
+ CError_ASSERT(497, pic_base_reg);
+ } else {
+ CError_FATAL(500);
+ }
+ } else {
+ pic_base_reg = 0;
+ }
+
+ for (list = exceptionlist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+
+ set_last_exception_registers();
+
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ if (!IsTempName(obj->name)) {
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+ }
+
+ open_fe_temp_registers();
+
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ if (IsTempName(obj->name)) {
+ vi = Registers_GetVarInfo(obj);
+
+ if (vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && !vi->reg)
+ assign_register_by_type(obj);
+ }
+ }
+ }
+
+ for (list = toclist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+
+ if (!vi->reg && vi->used && vi->usage > 1)
+ assign_register_by_type(obj);
+ }
+}
+
+static void allocate_local_GPRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+ Type *type;
+
+ if (copts.codegen_pic && uses_globals && assignable_registers[RegClass_GPR]) {
+ vi = pic_base.u.var.info;
+ vi->reg = 0;
+ assign_register_by_type(&pic_base);
+ pic_base_reg = vi->reg;
+ CError_ASSERT(605, pic_base_reg);
+ } else {
+ pic_base_reg = 0;
+ }
+
+ while (assignable_registers[RegClass_GPR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (TYPE_FITS_IN_REGISTER(type) && (!TYPE_IS_8BYTES(type) || assignable_registers[RegClass_GPR] >= 2)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ for (list = toclist; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used) {
+ if (vi->usage >= winning_usage && vi->usage >= 3) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+ CError_ASSERT(698, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_local_FPRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+ Type *type;
+
+ while (assignable_registers[RegClass_FPR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ type = obj->type;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_FLOAT(type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_FLOAT(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+ CError_ASSERT(782, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_local_VRs(void) {
+ ObjectList *list;
+ Object *obj;
+ Object *winning_obj;
+ SInt32 winning_usage;
+ VarInfo *vi;
+
+ while (assignable_registers[RegClass_VR]) {
+ winning_obj = NULL;
+ winning_usage = -1;
+ if (!(disable_optimizer & 2)) {
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_VECTOR(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+ if (!(disable_optimizer & 2)) {
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ vi = Registers_GetVarInfo(obj);
+ if (vi->flags & VarInfoFlag40)
+ vi->usage = 100000;
+ if (!vi->reg && vi->used && !vi->noregister) {
+ if (!OBJ_GET_TARGET_VOLATILE(obj) && vi->usage >= winning_usage && vi->usage >= 2) {
+ if (IS_TYPE_VECTOR(obj->type)) {
+ winning_obj = obj;
+ winning_usage = vi->usage;
+ }
+ }
+ }
+ }
+ }
+
+ if (!winning_obj)
+ break;
+
+ assign_register_by_type(winning_obj);
+ CError_ASSERT(846, Registers_GetVarInfo(winning_obj)->flags & VarInfoFlag2);
+ }
+}
+
+static void allocate_locals(void) {
+ has_altivec_arrays = 0;
+
+ if (!requires_frame && !optimizing)
+ process_arguments(retain_argument_register, 0);
+
+ if (optimizing) {
+ allocate_local_vregs();
+ } else {
+ allocate_local_GPRs();
+ allocate_local_FPRs();
+ allocate_local_VRs();
+ }
+
+ assign_locals_to_memory(locals);
+}
+
+void move_assigned_argument(Object *obj, short reg) {
+ VarInfo *vi;
+ Type *type;
+ SInt32 bytesLeft;
+ SInt32 offset;
+
+ vi = Registers_GetVarInfo(obj);
+ type = obj->type;
+ CError_ASSERT(901, obj->datatype == DLOCAL);
+
+ if (!vi->used)
+ return;
+
+ if (reg) {
+ if (vi->reg) {
+ if (TYPE_IS_8BYTES(type)) {
+ if (copts.littleendian) {
+ if (vi->reg != reg)
+ emitpcode(PC_MR, vi->reg, reg);
+ if (reg < GPRLimit) {
+ CError_FAIL(916, (vi->regHi == reg) || (vi->reg == (reg + 1)));
+ if (vi->regHi != (reg + 1))
+ emitpcode(PC_MR, vi->regHi, reg + 1);
+ } else {
+ load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset);
+ }
+ } else {
+ if (vi->regHi != reg)
+ emitpcode(PC_MR, vi->regHi, reg);
+ if (reg < GPRLimit) {
+ CError_FAIL(931, (vi->reg == reg) || (vi->regHi == (reg + 1)));
+ if (vi->reg != (reg + 1))
+ emitpcode(PC_MR, vi->reg, reg + 1);
+ } else {
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset);
+ }
+ }
+ } else if (vi->reg != reg) {
+ if (IS_TYPE_FLOAT(type)) {
+ emitpcode(PC_FMR, vi->reg, reg);
+ } else if (IS_TYPE_VECTOR(type)) {
+ emitpcode(PC_VMR, vi->reg, reg);
+ } else {
+ emitpcode(PC_MR, vi->reg, reg);
+ }
+ }
+ } else {
+ if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) {
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ load_store_register(PC_STB, reg, local_base_register(obj), obj, 0);
+ break;
+ case 2:
+ load_store_register(PC_STH, reg, local_base_register(obj), obj, 0);
+ break;
+ case 4:
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ break;
+ case 8:
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, 0);
+ if (reg < GPRLimit)
+ load_store_register(PC_STW, reg + 1, local_base_register(obj), obj, 4);
+ break;
+ default:
+ CError_FATAL(993);
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_VECTOR(type)) {
+ load_store_register(PC_STVX, reg, local_base_register(obj), obj, 0);
+ } else {
+ bytesLeft = (11 - reg) * 4;
+ if (bytesLeft > obj->type->size)
+ bytesLeft = obj->type->size;
+ offset = 0;
+ while (bytesLeft > 0) {
+ load_store_register(PC_STW, reg, local_base_register(obj), obj, offset);
+ reg++;
+ offset += 4;
+ bytesLeft -= 4;
+ }
+ }
+ }
+ } else {
+ if (vi->reg) {
+ if (IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type)) {
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_FLOAT(type)) {
+ load_store_register((type->size == 4) ? PC_LFS : PC_LFD, vi->reg, local_base_register(obj), obj, 0);
+ } else if (IS_TYPE_VECTOR(type)) {
+ load_store_register(PC_LVX, vi->reg, local_base_register(obj), obj, 0);
+ } else {
+ switch (type->size) {
+ case 1:
+ load_store_register(PC_LBZ, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 2:
+ load_store_register(is_unsigned(type) ? PC_LHZ : PC_LHA, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 4:
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, 0);
+ break;
+ case 8:
+ load_store_register(PC_LWZ, vi->regHi, local_base_register(obj), obj, high_offset);
+ load_store_register(PC_LWZ, vi->reg, local_base_register(obj), obj, low_offset);
+ break;
+ default:
+ CError_FATAL(1095);
+ }
+ }
+ } else if (!optimizing) {
+ local_base_register(obj);
+ }
+ }
+}
+
+static void load_TOC_pointers(void) {
+ VarInfo *vi;
+ Object *obj;
+ ObjectList *list;
+ PCode *pc;
+ Operand opnd;
+
+ if (uses_globals && pic_base_reg) {
+ pic_base_pcodelabel = makepclabel();
+ pc = makepcode(PC_BC, 20, 7, 3, pic_base_pcodelabel);
+ pcsetlinkbit(pc);
+ pcsetsideeffects(pc);
+ appendpcode(pclastblock, pc);
+ pcbranch(pclastblock, pic_base_pcodelabel);
+ makepcblock();
+ pclabel(pclastblock, pic_base_pcodelabel);
+ emitpcode(PC_MFLR, pic_base_reg);
+ }
+
+ memclrw(&opnd, sizeof(Operand));
+ for (list = toclist; list; list = list->next) {
+ obj = list->object;
+ if ((vi = Registers_GetVarInfo(obj)) && (vi->flags & VarInfoFlag2)) {
+ switch (obj->datatype) {
+ case DNONLAZYPTR:
+ symbol_operand(&opnd, obj);
+ opnd.optype = OpndType_IndirectSymbol;
+ if (opnd.optype)
+ Coerce_to_register(&opnd, TYPE(&void_ptr), vi->reg);
+ if (opnd.reg != vi->reg)
+ emitpcode(PC_MR, vi->reg, opnd.reg);
+ break;
+ default:
+ CError_FATAL(1206);
+ }
+ }
+ }
+}
+
+static int has_vararglist(Object *funcobj) {
+ FuncArg *arg;
+
+ arg = TYPE_FUNC(funcobj->type)->args;
+ while (arg && arg != &elipsis)
+ arg = arg->next;
+
+ return (arg == &elipsis);
+}
+
+void assign_labels(Statement *stmt) {
+ Statement *last;
+
+ last = NULL;
+ while (stmt) {
+ if (stmt->type == ST_LABEL && !stmt->label->pclabel) {
+ if (last && last->type == ST_LABEL)
+ stmt->label->pclabel = last->label->pclabel;
+ else
+ stmt->label->pclabel = makepclabel();
+ }
+
+ last = stmt;
+ stmt = stmt->next;
+ }
+}
+
+static Boolean islaststatement(Statement *stmt) {
+ for (stmt = stmt->next; stmt; stmt = stmt->next) {
+ if (stmt->type > ST_LABEL)
+ return 0;
+ }
+ return 1;
+}
+
+static void newstatement(SInt32 sourceoffset, SInt32 value, int flag) {
+ PCodeBlock *block = pclastblock;
+
+ pcloopweight = value;
+ if (!block->pcodeCount)
+ block->loopWeight = value;
+
+ if (block->pcodeCount > 100)
+ branch_label(makepclabel());
+
+ if (flag)
+ block->flags |= fPCBlockFlag4000;
+}
+
+static void expressionstatement(ENode *expr) {
+ Operand opnd;
+
+ memclrw(&opnd, sizeof(Operand));
+ cgdispatch[expr->type](expr, 0, 0, &opnd);
+
+ if (ENODE_IS(expr, EINDIRECT) && (opnd.flags & OpndFlags_Volatile)) {
+ if (TYPE_FITS_IN_REGISTER_2(expr->rtype)) {
+ if (opnd.optype != OpndType_GPR)
+ Coerce_to_register(&opnd, expr->rtype, 0);
+ } else if (IS_TYPE_FLOAT(expr->rtype)) {
+ if (opnd.optype != OpndType_FPR)
+ Coerce_to_fp_register(&opnd, expr->rtype, 0);
+ } else if (IS_TYPE_VECTOR(expr->rtype)) {
+ if (opnd.optype != OpndType_VR)
+ Coerce_to_v_register(&opnd, expr->rtype, 0);
+ }
+ }
+}
+
+static void labelstatement(CLabel *label) {
+ if (!label->pclabel)
+ label->pclabel = makepclabel();
+ if (!label->pclabel->resolved)
+ branch_label(label->pclabel);
+ free_temporaries();
+}
+
+static void gotostatement(CLabel *label) {
+ if (!label->pclabel)
+ label->pclabel = makepclabel();
+ branch_always(label->pclabel);
+ free_temporaries();
+}
+
+static void gotoexpression(ENode *expr) {
+ Operand opnd;
+ CodeLabelList *list;
+
+ memclrw(&opnd, sizeof(Operand));
+ cgdispatch[expr->type](expr, 0, 0, &opnd);
+
+ if (opnd.optype != OpndType_GPR)
+ Coerce_to_register(&opnd, TYPE(&void_ptr), 0);
+ CError_ASSERT(1397, opnd.optype == OpndType_GPR);
+
+ for (list = codelabellist; list; list = list->next)
+ pcbranch(pclastblock, list->label->pclabel);
+
+ emitpcode(PC_MTCTR, opnd.reg);
+ branch_indirect(NULL);
+}
+
+static void conditionalstatement(ENode *cond, CLabel *label, short truthy) {
+ Operand opnd;
+ memclrw(&opnd, sizeof(Operand));
+
+ cond = evaluate_and_skip_comma(cond);
+ if (!label->pclabel)
+ label->pclabel = makepclabel();
+
+ if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype))
+ I8_gen_condition(cond, &opnd, 0);
+ else
+ gen_condition(cond, &opnd);
+
+ branch_conditional(opnd.reg, opnd.regOffset, truthy, label->pclabel);
+ free_temporaries();
+}
+
+static void returnstatement(ENode *expr, Boolean dont_branch) {
+ Operand opnd;
+ Type *type;
+ memclrw(&opnd, sizeof(Operand));
+
+ if (expr) {
+ type = expr->rtype;
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (TYPE_IS_8BYTES(type)) {
+ cgdispatch[expr->type](expr, low_reg, high_reg, &opnd);
+ coerce_to_register_pair(&opnd, type, low_reg, high_reg);
+ } else {
+ cgdispatch[expr->type](expr, 3, 0, &opnd);
+ if (opnd.optype != OpndType_GPR)
+ Coerce_to_register(&opnd, type, 3);
+ if (opnd.reg != 3)
+ emitpcode(PC_MR, 3, opnd.reg);
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ cgdispatch[expr->type](expr, 1, 0, &opnd);
+ if (opnd.optype != OpndType_FPR)
+ Coerce_to_fp_register(&opnd, type, 1);
+ if (opnd.reg != 1)
+ emitpcode(PC_FMR, 1, opnd.reg);
+ } else if (IS_TYPE_VECTOR(type)) {
+ cgdispatch[expr->type](expr, 2, 0, &opnd);
+ if (opnd.optype != OpndType_VR)
+ Coerce_to_v_register(&opnd, type, 2);
+ if (opnd.reg != 2)
+ emitpcode(PC_VMR, 2, opnd.reg);
+ } else {
+ cgdispatch[expr->type](expr, 0, 0, &opnd);
+ }
+ }
+
+ if (!dont_branch) {
+ if (!returnlabel->pclabel)
+ returnlabel->pclabel = makepclabel();
+ branch_always(returnlabel->pclabel);
+ free_temporaries();
+ }
+}
+
+static void capturestackpointer(Object *obj) {
+ branch_label(makepclabel());
+ CError_ASSERT(1568, obj->datatype == DLOCAL);
+
+ load_store_register(PC_STW, 1, local_base_register(obj), obj, 20);
+ branch_label(makepclabel());
+}
+
+static void resetstackpointer(Object *obj) {
+ PCode *pc;
+
+ CError_ASSERT(1595, obj->datatype == DLOCAL);
+
+ branch_label(makepclabel());
+
+ load_store_register(PC_LWZ, 0, 1, NULL, 0);
+
+ pc = makepcode(PC_LWZ, 1, local_base_register(obj), obj, 20);
+ pcsetsideeffects(pc);
+ appendpcode(pclastblock, pc);
+
+ load_store_register(PC_STW, 0, 1, NULL, 0);
+
+ branch_label(makepclabel());
+}
+
+static void callprofiler(char *name) {
+ UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0};
+ load_store_register(PC_LWZ, 3, 1, NULL, 0);
+ load_store_register(PC_LWZ, 3, 3, NULL, 8);
+ masks[RegClass_GPR] |= (1 << 3);
+ branch_subroutine(rt_profile_entry, 1, masks);
+}
+
+static void exitprofiler(void) {
+}
+
+void CodeGen_Generator(Statement *statements, Object *func, UInt8 mysteryFlag, Boolean callOnModuleBind) {
+ Statement *stmt;
+ Boolean has_varargs;
+ PCodeBlock *tmp;
+ SInt32 size;
+
+ CodeGen_InitialSanityCheck();
+ if (!saveheaperror) {
+ saveheaperror = getheaperror();
+ setheaperror(CodeGen_heaperror);
+ }
+
+ if (cparamblkptr->precompile == 1)
+ CError_Error(CErrorStr180);
+
+ if (!func) {
+ func = createstaticinitobject();
+ } else {
+#ifdef CW_CLT
+ if (func && func->name)
+ PrintProgressFunction(func->name->name);
+#endif
+ }
+
+ gFunction = func;
+ has_varargs = has_vararglist(func);
+ init_endian();
+ init_stack_globals(func);
+ assign_arguments_to_memory(func, mysteryFlag, has_varargs);
+
+ needs_cleanup = 0;
+ disable_optimizer = 0;
+ has_catch_blocks = 0;
+ current_statement = NULL;
+ current_linenumber = 0;
+ precomputedoperands = NULL;
+ switchtables = NULL;
+ temps = NULL;
+ initializeexceptiontables();
+ returnlabel = cleanreturnlabel = newlabel();
+
+ if (copts.debuglisting)
+ DumpIR(statements, func);
+
+ statements = COpt_Optimizer(func, statements);
+ if (copts.debuglisting)
+ DumpIR(statements, func);
+
+ resetTOCvarinfo();
+ init_registers();
+ expandTOCreferences(&statements->next);
+ if (copts.debuglisting)
+ DumpIR(statements, func);
+
+ if (copts.profile) {
+ makes_call = 1;
+ requires_frame = 1;
+ }
+
+ initpcode();
+
+ pclabel(prologue = makepcblock(), makepclabel());
+ prologue->flags |= fIsProlog;
+
+ pclabel(tmp = makepcblock(), makepclabel());
+ pcbranch(prologue, tmp->labels);
+
+ init_frame_sizes(has_varargs);
+ allocate_locals();
+ process_arguments(move_assigned_argument, has_varargs);
+
+ if (copts.schedule_factor || copts.altivec_model)
+ branch_label(makepclabel());
+
+ load_TOC_pointers();
+
+ if (copts.profile)
+ callprofiler(CMangler_GetLinkName(func)->name);
+
+ assign_labels(statements->next);
+ open_temp_registers();
+
+ for (stmt = statements->next; stmt; stmt = stmt->next) {
+ current_statement = stmt;
+ current_linenumber = stmt->sourceoffset;
+ switch (stmt->type) {
+ case ST_NOP:
+ break;
+ case ST_EXPRESSION:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ expressionstatement(stmt->expr);
+ break;
+ case ST_LABEL:
+ labelstatement(stmt->label);
+ break;
+ case ST_IFGOTO:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ conditionalstatement(stmt->expr, stmt->label, 1);
+ break;
+ case ST_IFNGOTO:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ conditionalstatement(stmt->expr, stmt->label, 0);
+ break;
+ case ST_GOTOEXPR:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ gotoexpression(stmt->expr);
+ break;
+ case ST_GOTO:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ gotostatement(stmt->label);
+ break;
+ case ST_RETURN:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ returnstatement(stmt->expr, islaststatement(stmt));
+ break;
+ case ST_SWITCH:
+ newstatement(stmt->sourceoffset, stmt->value, (stmt->flags & StmtFlag_10) != 0);
+ switchstatement(stmt->expr, (SwitchInfo *) stmt->label);
+ break;
+ case ST_BEGINCATCH:
+ capturestackpointer(stmt->expr->data.objref);
+ break;
+ case ST_ENDCATCHDTOR:
+ CError_ASSERT(2056, stmt->expr->data.objref->datatype == DLOCAL);
+ add_immediate(3, local_base_register(stmt->expr->data.objref), stmt->expr->data.objref, 0);
+ {
+ UInt32 masks[RegClassMax] = {0, 0, 0, 0, 0};
+ masks[RegClass_GPR] |= 1 << 3;
+ branch_subroutine(Xecth_func, 1, masks);
+ }
+ case ST_ENDCATCH:
+ resetstackpointer(stmt->expr->data.objref);
+ break;
+ case ST_ASM:
+ if (stmt->expr) {
+ if (((InlineAsm *) stmt->expr)->flags & IAFlag1) {
+ CError_FATAL(2076);
+ } else {
+ branch_label(makepclabel());
+ InlineAsm_TranslateIRtoPCode(stmt);
+ }
+ }
+ break;
+ case ST_BEGINLOOP:
+ CError_FATAL(2086);
+ break;
+ case ST_ENDLOOP:
+ CError_FATAL(2090);
+ break;
+ default:
+ CError_FATAL(2094);
+ }
+ check_temp_registers();
+ }
+
+ close_temp_registers();
+ labelstatement(returnlabel);
+
+ current_statement = NULL;
+
+ epilogue = pclastblock;
+ pclastblock->flags |= fIsEpilogue;
+
+ pccomputepredecessors();
+ deleteunreachableblocks();
+
+ if (copts.report_heap_info > 0)
+ CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "before optimization");
+
+ if (copts.optimizationlevel > 0 && !disable_optimizer)
+ globallyoptimizepcode(func);
+ else
+ pclistblocks(CMangler_GetLinkName(func)->name, "INITIAL CODE");
+
+ if (copts.schedule_factor == 2) {
+ if (copts.peephole)
+ peepholemergeblocks(func, 0);
+ if (copts.debuglisting)
+ pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING");
+ scheduleinstructions(0);
+ if (copts.debuglisting)
+ pclistblocks_end_scheduler();
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSTRUCTION SCHEDULING");
+ }
+
+ if (copts.peephole) {
+ if (copts.schedule_factor == 0 && copts.optimizationlevel > 1)
+ peepholemergeblocks(func, 0);
+ peepholeoptimizeforward(func);
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE FORWARD");
+ }
+
+ allocate_temporaries();
+ colorinstructions(func);
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER REGISTER COLORING");
+
+ if (copts.optimizationlevel > 1 && !disable_optimizer) {
+ removecommonsubexpressions(func, 1);
+ if (removedcommonsubexpressions && copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER VALUE NUMBERING (POST COLORING)");
+ }
+
+ compute_frame_sizes();
+ generate_prologue(prologue, has_varargs);
+ if (copts.profile)
+ exitprofiler();
+ generate_epilogue(epilogue, 1);
+
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER GENERATING EPILOGUE, PROLOGUE");
+
+ if (copts.peephole) {
+ if (copts.schedule_factor) {
+ peepholemergeblocks(func, 1);
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER MERGING EPILOGUE, PROLOGUE");
+ }
+ peepholeoptimizepcode(func);
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER PEEPHOLE OPTIMIZATION");
+ }
+
+ if (copts.schedule_factor) {
+ if (copts.debuglisting)
+ pclistblocks_start_scheduler(CMangler_GetLinkName(func)->name, "BEFORE SCHEDULING");
+ scheduleinstructions(1);
+ if (copts.debuglisting)
+ pclistblocks_end_scheduler();
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE AFTER INSTRUCTION SCHEDULING");
+ } else {
+ if (copts.debuglisting)
+ pclistblocks(CMangler_GetLinkName(func)->name, "FINAL CODE");
+ }
+
+ size = assemblefunction(func, NULL);
+ dumpswitchtables(func);
+ dumpcodelabels(func);
+ if (callOnModuleBind)
+ ObjGen_DeclareInitFunction(func);
+
+ pic_base_pcodelabel = NULL;
+ pic_base_reg = 0;
+ if (copts.exceptions && requires_frame)
+ dumpexceptiontables(func, size);
+
+ if (copts.report_heap_info > 0)
+ CodeGen_reportheapinfo(0, CMangler_GetLinkName(func)->name, "finished");
+
+ if (saveheaperror)
+ setheaperror(saveheaperror);
+}
+
+enum {
+ reg3 = 3,
+ reg4 = 4
+};
+
+void CodeGen_GenVDispatchThunk(Object *thunkobj, Object *obj, SInt32 a, SInt32 b, SInt32 c) {
+ Boolean save_debug;
+ Boolean save_peephole;
+ Boolean save_traceback;
+ char reg;
+
+ save_debug = copts.filesyminfo;
+ save_peephole = copts.peephole;
+ save_traceback = copts.traceback;
+
+ CodeGen_InitialSanityCheck();
+ CError_ASSERT(2270, b == 0);
+
+ initpcode();
+ makepcblock();
+
+ if (a) {
+ reg = CMach_PassResultInHiddenArg(TYPE_FUNC(obj->type)->functype) ? reg4 : reg3;
+
+ if (c >= 0) {
+ if (!FITS_IN_SHORT(c)) {
+ emitpcode(PC_ADDIS, 11, 0, 0, HIGH_PART(c));
+ if (c)
+ emitpcode(PC_ADDI, 11, 11, 0, LOW_PART(c));
+ } else {
+ emitpcode(PC_ADDI, 11, 0, 0, c);
+ }
+ emitpcode(PC_LWZX, 11, reg, 11);
+ emitpcode(PC_ADD, reg, reg, 11);
+ }
+
+ if (!FITS_IN_SHORT(a)) {
+ emitpcode(PC_ADDIS, reg, reg, 0, HIGH_PART(a));
+ if (a)
+ emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(a));
+ } else {
+ emitpcode(PC_ADDI, reg, reg, 0, a);
+ }
+ }
+
+ emitpcode(PC_B, 0, obj);
+
+ copts.filesyminfo = 0;
+ copts.peephole = 0;
+ copts.traceback = 0;
+ assemblefunction(thunkobj, NULL);
+ copts.filesyminfo = save_debug;
+ copts.peephole = save_peephole;
+ copts.traceback = save_traceback;
+}
+
+void CodeGen_SetupRuntimeObjects(void) {
+ setupaddressing();
+ dyld_stub_binding_helper = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_fp2unsigned = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_profile_entry = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_profile_exit = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_div2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_div2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_mod2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_mod2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_shr2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_shr2u = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_shl2i = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_ull_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_sll_dbl = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_ull_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_sll_flt = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ rt_cvt_dbl_usll = CParser_NewRTFunc(&stvoid, NULL, 2, 0);
+ Intrinsics_SetupRuntimeObjects();
+}
+
+Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) {
+ dyld_stub_binding_helper->name = GetHashNameNodeExport("dyld_stub_binding_helper");
+ dyld_stub_binding_helper->u.func.linkname = dyld_stub_binding_helper->name;
+
+ rt_cvt_fp2unsigned->name = GetHashNameNodeExport("__cvt_fp2unsigned");
+
+ rt_profile_entry->name = GetHashNameNodeExport("mcount");
+ rt_profile_entry->u.func.linkname = rt_profile_entry->name;
+
+ rt_profile_exit->name = GetHashNameNodeExport("profile_exit");
+
+ rt_div2i->name = GetHashNameNodeExport("__div2i");
+ rt_div2u->name = GetHashNameNodeExport("__div2u");
+ rt_mod2i->name = GetHashNameNodeExport("__mod2i");
+ rt_mod2u->name = GetHashNameNodeExport("__mod2u");
+ rt_shr2i->name = GetHashNameNodeExport("__shr2i");
+ rt_shr2u->name = GetHashNameNodeExport("__shr2u");
+ rt_shl2i->name = GetHashNameNodeExport("__shl2i");
+
+ rt_cvt_ull_dbl->name = GetHashNameNodeExport("__cvt_ull_dbl");
+ rt_cvt_sll_dbl->name = GetHashNameNodeExport("__cvt_sll_dbl");
+ rt_cvt_ull_flt->name = GetHashNameNodeExport("__cvt_ull_flt");
+ rt_cvt_sll_flt->name = GetHashNameNodeExport("__cvt_sll_flt");
+ rt_cvt_dbl_usll->name = GetHashNameNodeExport("__cvt_dbl_usll");
+
+ CMach_ReInitRuntimeObjects();
+ return Intrinsics_ReInitRuntimeObjects(is_precompiler);
+}
+
+Boolean CodeGen_IsPublicRuntimeObject(Object *obj) {
+ return Intrinsics_IsPublicRuntimeObject(obj);
+}
+
+void CodeGen_SOMStub(Object *a, Object *b, Object *c, SInt32 offset) {
+ Boolean save_debug;
+ Boolean save_peephole;
+ Boolean save_traceback;
+ Object *tmp;
+ Operand opnd;
+
+ save_debug = copts.filesyminfo;
+ save_peephole = copts.peephole;
+ save_traceback = copts.traceback;
+
+ CodeGen_InitialSanityCheck();
+ memclrw(&opnd, sizeof(Operand));
+ CError_ASSERT(2528, offset <= 0x7FFF);
+
+ initpcode();
+ makepcblock();
+
+ tmp = createIndirect(c, 1, 1);
+ if (tmp) {
+ opnd.optype = OpndType_Symbol;
+ opnd.object = tmp;
+ indirect(&opnd, NULL);
+ } else {
+ opnd.optype = OpndType_Symbol;
+ opnd.object = c;
+ }
+
+ if (opnd.optype != OpndType_GPR)
+ Coerce_to_register(&opnd, TYPE(&void_ptr), 12);
+
+ if (opnd.optype != OpndType_GPR) {
+ CError_FATAL(2562);
+ } else if (opnd.reg != 12) {
+ emitpcode(PC_MR, 12, opnd.reg);
+ }
+
+ load_store_register(PC_LWZ, 12, 12, NULL, (short) offset);
+ emitpcode(PC_B, 0, b);
+
+ copts.filesyminfo = 0;
+ copts.peephole = 0;
+ copts.traceback = 0;
+ assemblefunction(a, NULL);
+ copts.filesyminfo = save_debug;
+ copts.peephole = save_peephole;
+ copts.traceback = save_traceback;
+}
+
+void CodeGen_ParseDeclSpec(HashNameNode *identifier, DeclInfo *declinfo) {
+ if (!strcmp(identifier->name, "private_extern")) {
+ declinfo->storageclass = TK_EXTERN;
+ declinfo->exportflags = EXPORT_FLAGS_INTERNAL;
+ } else {
+ CError_Error(CErrorStr176);
+ }
+}
+
+static void CodeGen_EOLCheck(void) {
+ short t;
+
+ if (plex() != TK_EOL) {
+ CPrep_Error(CErrorStr113);
+ do {
+ t = plex();
+ } while (t != TK_EOL && t != 0);
+ }
+}
+
+static void schedule_for(int what) {
+ CPrep_PushOption(OPT_OFFSET(scheduling), what);
+ if (copts.schedule_factor == 0)
+ CPrep_PushOption(OPT_OFFSET(schedule_factor), 2);
+}
+
+static void pragma_scheduling(void) {
+ Boolean *flag;
+ int cpu;
+
+ tk = plex();
+ if (tk == TK_IDENTIFIER) {
+ flag = &copts.altivec_model;
+ if (!strcmp(tkidentifier->name, "vger")) {
+ schedule_for(10);
+ return;
+ } else if (!strcmp(tkidentifier->name, "altivec")) {
+ schedule_for(7);
+ return;
+ } else if (!strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(scheduling));
+ CPrep_PopOption(OPT_OFFSET(schedule_factor));
+ return;
+ } else if (!strcmp(tkidentifier->name, "off")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_factor), 0);
+ return;
+ } else if (!strcmp(tkidentifier->name, "once")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_factor), 1);
+ return;
+ } else if (!strcmp(tkidentifier->name, "twice")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_factor), 2);
+ return;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_factor), 2);
+ return;
+ } else if (!*flag) {
+ if (!strcmp(tkidentifier->name, "603e")) {
+ schedule_for(5);
+ return;
+ } else if (!strcmp(tkidentifier->name, "604e")) {
+ schedule_for(6);
+ return;
+ } else if (!strcmp(tkidentifier->name, "PPC603e")) {
+ schedule_for(5);
+ return;
+ } else if (!strcmp(tkidentifier->name, "PPC604e")) {
+ schedule_for(6);
+ return;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr115);
+ return;
+ }
+ CPrep_Error(CErrorStr186);
+ return;
+ }
+
+ if (tk == TK_INTCONST) {
+ switch (CInt64_GetULong(&tkintconst)) {
+ case 601:
+ cpu = 1;
+ break;
+ case 603:
+ cpu = 2;
+ break;
+ case 604:
+ cpu = 3;
+ break;
+ case 750:
+ cpu = 4;
+ break;
+ case 7400:
+ cpu = 7;
+ break;
+ case 7450:
+ cpu = 10;
+ break;
+ case 8240:
+ case 8260:
+ cpu = 5;
+ break;
+ case 801:
+ case 821:
+ case 823:
+ case 850:
+ case 860:
+ cpu = 9;
+ break;
+ default:
+ CPrep_Error(CErrorStr186);
+ return;
+ }
+ schedule_for(cpu);
+ return;
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(CErrorStr186);
+}
+
+static SInt32 CodeGen_ParseLongIntegerORonORoff(void) {
+ SInt32 result;
+ short t;
+
+ result = 0;
+ t = plex();
+ if (t == TK_INTCONST) {
+ if (!tkintconst.hi)
+ result = CInt64_GetULong(&tkintconst);
+ else
+ CPrep_Error(CErrorStr154);
+ CodeGen_EOLCheck();
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "on")) {
+ CodeGen_EOLCheck();
+ return 1;
+ }
+ if (!strcmp(tkidentifier->name, "off")) {
+ CodeGen_EOLCheck();
+ return 0;
+ }
+ if (copts.warn_illpragma)
+ CPrep_Warning(CErrorStr186);
+ return 0;
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(CErrorStr186);
+ }
+
+ return result;
+}
+
+void CodeGen_ParsePragma(HashNameNode *name) {
+ short t;
+ SInt32 value;
+ char *str;
+ NameSpace *nspace;
+ NameSpaceObjectList *list;
+
+ if (!strcmp(name->name, "debuglisting")) {
+ copts.debuglisting = CodeGen_ParseLongIntegerORonORoff();
+ return;
+ }
+
+ if (!strcmp(name->name, "report_heap_info")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ copts.report_heap_info = CInt64_GetULong(&tkintconst);
+ if (copts.report_heap_info < 0) {
+ copts.report_heap_info = 0;
+ CError_Error(CErrorStr186);
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.report_heap_info = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.report_heap_info = 1;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "scheduling")) {
+ pragma_scheduling();
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "ppc_unroll_speculative")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.unroll_speculative = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.unroll_speculative = 1;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "ppc_unroll_instructions_limit")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ copts.unroll_instr_limit = CInt64_GetULong(&tkintconst);
+ if (copts.unroll_instr_limit < 0) {
+ copts.unroll_instr_limit = 0;
+ CError_Error(CErrorStr186);
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.unroll_instr_limit = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.unroll_instr_limit = 70;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "gen_fsel")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ value = CInt64_GetULong(&tkintconst);
+ if (value < 0) {
+ copts.gen_fsel = 0;
+ CError_Error(CErrorStr186);
+ } else if (value > 255) {
+ copts.gen_fsel = 255;
+ CError_Error(CErrorStr186);
+ } else {
+ copts.gen_fsel = value;
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.gen_fsel = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.gen_fsel = 10;
+ } else if (!strcmp(tkidentifier->name, "always")) {
+ copts.gen_fsel = 255;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "ppc_unroll_factor_limit")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ copts.unroll_factor_limit = CInt64_GetULong(&tkintconst);
+ if (copts.unroll_factor_limit < 0) {
+ copts.unroll_factor_limit = 0;
+ CError_Error(CErrorStr186);
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.unroll_factor_limit = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.unroll_factor_limit = 10;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "altivec_model")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.altivec_model = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.altivec_model = 1;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "altivec_vrsave")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 0);
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 1);
+ } else if (!strcmp(tkidentifier->name, "allon")) {
+ CPrep_PushOption(OPT_OFFSET(altivec_vrsave), 2);
+ } else if (!strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(altivec_vrsave));
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "function_align")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ value = CInt64_GetULong(&tkintconst);
+ switch (value) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ CPrep_PushOption(OPT_OFFSET(function_align), value);
+ break;
+ default:
+ PPCError_Warning(PPCErrorStr161);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(function_align));
+ } else {
+ PPCError_Warning(PPCErrorStr161);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "processor")) {
+ if (cscope_currentfunc) {
+ PPCError_Warning(PPCErrorStr156, "pragma processor");
+ return;
+ }
+ t = plex();
+ if (t == TK_INTCONST) {
+ switch (CInt64_GetULong(&tkintconst)) {
+ case 401:
+ copts.processor = 0;
+ break;
+ case 403:
+ copts.processor = 1;
+ break;
+ case 505:
+ copts.processor = 2;
+ break;
+ case 509:
+ copts.processor = 3;
+ break;
+ case 555:
+ copts.processor = 4;
+ break;
+ case 556:
+ copts.processor = 25;
+ break;
+ case 565:
+ copts.processor = 26;
+ break;
+ case 601:
+ copts.processor = 5;
+ break;
+ case 602:
+ copts.processor = 6;
+ break;
+ case 8240:
+ copts.processor = 18;
+ break;
+ case 8260:
+ copts.processor = 19;
+ break;
+ case 603:
+ copts.processor = 7;
+ break;
+ case 604:
+ copts.processor = 9;
+ break;
+ case 740:
+ copts.processor = 11;
+ break;
+ case 750:
+ copts.processor = 12;
+ break;
+ case 801:
+ copts.processor = 13;
+ break;
+ case 821:
+ copts.processor = 14;
+ break;
+ case 823:
+ copts.processor = 15;
+ break;
+ case 850:
+ copts.processor = 16;
+ break;
+ case 860:
+ copts.processor = 17;
+ break;
+ case 7400:
+ copts.processor = 21;
+ break;
+ default:
+ PPCError_Warning(PPCErrorStr208);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "generic"))
+ copts.processor = 20;
+ else if (!strcmp(tkidentifier->name, "603e"))
+ copts.processor = 8;
+ else if (!strcmp(tkidentifier->name, "604e"))
+ copts.processor = 10;
+ else if (!strcmp(tkidentifier->name, "PPC603e"))
+ copts.processor = 8;
+ else if (!strcmp(tkidentifier->name, "PPC604e"))
+ copts.processor = 10;
+ else
+ PPCError_Warning(PPCErrorStr208);
+ } else {
+ PPCError_Warning(PPCErrorStr208);
+ }
+
+ if ((str = CMach_GetCPU()))
+ CPrep_InsertSpecialMacro(&ppc_cpu, str);
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "min_struct_alignment")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ value = CInt64_GetULong(&tkintconst);
+ switch (value) {
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ CPrep_PushOption(OPT_OFFSET(min_struct_alignment), value);
+ break;
+ default:
+ PPCError_Warning(PPCErrorStr191);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "reset"))
+ CPrep_PopOption(OPT_OFFSET(min_struct_alignment));
+ else if (!strcmp(tkidentifier->name, "on"))
+ CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 4);
+ else if (!strcmp(tkidentifier->name, "off"))
+ CPrep_PushOption(OPT_OFFSET(min_struct_alignment), 1);
+ } else {
+ PPCError_Warning(PPCErrorStr161);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "tvectors")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ no_descriptors = 1;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ no_descriptors = 0;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "dynamic")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.codegen_dynamic = 0;
+ copts.codegen_pic = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.codegen_dynamic = 1;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "pic")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.codegen_pic = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.codegen_pic = 1;
+ if (!copts.codegen_dynamic) {
+ PPCError_Error(PPCErrorStr189);
+ copts.codegen_pic = 0;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "implicit_templates")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.no_implicit_templates = 1;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.no_implicit_templates = 0;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "common")) {
+ if (plex() == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.no_common = 1;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.no_common = 0;
+ } else {
+ CError_Error(CErrorStr186);
+ return;
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "CALL_ON_MODULE_BIND")) {
+ if (plex() == TK_IDENTIFIER) {
+ for (nspace = cscope_current; nspace; nspace = nspace->parent) {
+ list = CScope_GetLocalObject(nspace, tkidentifier);
+ if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DFUNC) {
+ ObjGen_DeclareInitFunction(OBJECT(list->object));
+ break;
+ }
+ }
+ } else {
+ CError_Error(CErrorStr186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(CErrorStr186);
+
+ if (plex() != TK_EOL) {
+ do {
+ t = plex();
+ } while (t != TK_EOL && t != 0);
+ }
+}
+
+void CodeGen_UpdateObject(Object *object) {
+ if (object->datatype == DDATA && object->section == SECT_DEFAULT && object == rt_ptmf_null)
+ object->sclass = TK_EXTERN;
+}
+
+void CodeGen_UpdateBackEndOptions(void) {
+ copts.globaloptimizer = 1;
+}
+
+SInt32 CodeGen_objc_method_self_offset(ObjCMethod *meth) {
+ SInt32 size;
+
+ if (!meth->return_type) {
+ size = 4;
+ } else if (
+ IS_TYPE_ARRAY(meth->return_type) ||
+ IS_TYPE_NONVECTOR_STRUCT(meth->return_type) ||
+ IS_TYPE_CLASS(meth->return_type) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(meth->return_type)
+ )
+ {
+ size = 8;
+ } else {
+ size = meth->return_type->size;
+ }
+
+ if (size == 0)
+ size = 1;
+
+ return (size + 3) & ~3;
+}
+
+SInt32 CodeGen_objc_method_sel_offset(ObjCMethod *meth) {
+ return (CodeGen_objc_method_self_offset(meth) + 7) & ~3;
+}
+
+SInt32 CodeGen_objc_method_arg_offset(ObjCMethod *meth, ObjCMethodArg *arg) {
+ SInt32 pos;
+ ObjCMethodArg *scan;
+
+ pos = CodeGen_objc_method_sel_offset(meth) + 4;
+ for (scan = meth->selector_args; scan; scan = scan->next) {
+ if (scan == arg)
+ return pos;
+
+ if (scan->type == NULL)
+ pos += 4;
+ else
+ pos += scan->type->size;
+
+ pos = (pos + 3) & ~3;
+ }
+
+ return 0;
+}
+
+SInt32 CodeGen_objc_method_args_size(ObjCMethod *meth) {
+ SInt32 size;
+ ObjCMethodArg *scan;
+
+ size = CodeGen_objc_method_self_offset(meth);
+ for (scan = meth->selector_args; scan; scan = scan->next) {
+ if (scan->next == NULL && scan->type == NULL)
+ return size;
+
+ size = (size + 3) & ~3;
+ if (scan->type == NULL)
+ size += 4;
+ else
+ size += scan->type->size;
+ }
+
+ return size;
+}
+
+ENode *CodeGen_HandleIntrinsicCall(Object *func, ENodeList *arg_exprs) {
+ return Intrinsics_HandleIntrinsicCall(func, arg_exprs);
+}
+
+ENode *CodeGen_HandleTypeCast(ENode *expr, Type *type, UInt32 qual) {
+ short flags;
+
+ if (copts.altivec_model) {
+ flags = qual & ENODE_FLAG_QUALS;
+ if (IS_TYPE_STRUCT(type) && IS_TYPE_STRUCT(expr->rtype) && expr->flags == flags) {
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_VECTOR_UCHAR:
+ case STRUCT_VECTOR_SCHAR:
+ case STRUCT_VECTOR_BCHAR:
+ case STRUCT_VECTOR_USHORT:
+ case STRUCT_VECTOR_SSHORT:
+ case STRUCT_VECTOR_BSHORT:
+ case STRUCT_VECTOR_UINT:
+ case STRUCT_VECTOR_SINT:
+ case STRUCT_VECTOR_BINT:
+ case STRUCT_VECTOR_FLOAT:
+ case STRUCT_VECTOR_PIXEL:
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+short CodeGen_AssignCheck(const ENode *expr, const Type *type, Boolean flag1, Boolean flag2) {
+ short result;
+ const Type *exprtype = expr->rtype;
+
+ if (
+ copts.altivec_model &&
+ IS_TYPE_VECTOR(type) &&
+ IS_TYPE_VECTOR(exprtype) &&
+ TYPE_STRUCT(type)->stype == TYPE_STRUCT(exprtype)->stype
+ )
+ result = CheckResult3;
+ else
+ result = CheckResult0;
+ return result;
+}
+
+Boolean CodeGen_CollapseVectorExpression(ENode *expr, MWVector128 *vec, Type *type) {
+ // this function is a mess and needs lots of fixing
+ Boolean result;
+ //int count;
+ int i;
+ ENode *escan;
+
+ result = 0;
+ for (i = 0; i < 4; i++)
+ vec->ul[i] = 0;
+
+ if (ENODE_IS(expr, ECOMMA)) {
+ i = 0;
+ escan = expr;
+ while (ENODE_IS(escan, ECOMMA)) {
+ i++;
+ escan = escan->data.diadic.left;
+ }
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_VECTOR_UCHAR:
+ case STRUCT_VECTOR_SCHAR:
+ case STRUCT_VECTOR_BCHAR:
+ if (i < 15) {
+ PPCError_Error(PPCErrorStr110, type, 0);
+ } else if (i > 15) {
+ PPCError_Error(PPCErrorStr111, type, 0);
+ } else {
+ escan = expr;
+ i = 15;
+ while (ENODE_IS(escan, ECOMMA)) {
+ CInt64 v;
+ expr = escan->data.diadic.right;
+ v = expr->data.intval;
+ if (!ENODE_IS(expr, EINTCONST)) {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+
+ vec->uc[i--] = (UInt8) v.lo;
+ escan = escan->data.diadic.left;
+ }
+
+ if (ENODE_IS(escan, EINTCONST)) {
+ CInt64 v = escan->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ vec->uc[0] = (UInt8) v.lo;
+ } else {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_VECTOR_USHORT:
+ case STRUCT_VECTOR_SSHORT:
+ case STRUCT_VECTOR_BSHORT:
+ case STRUCT_VECTOR_PIXEL:
+ if (i < 7) {
+ PPCError_Error(PPCErrorStr110, type, 0);
+ } else if (i > 7) {
+ PPCError_Error(PPCErrorStr111, type, 0);
+ } else {
+ escan = expr;
+ i = 7;
+ while (ENODE_IS(escan, ECOMMA)) {
+ ENode *e = escan->data.diadic.right;
+ CInt64 v = e->data.intval;
+ if (!ENODE_IS(e, EINTCONST)) {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+
+ vec->us[i--] = (UInt16) e->data.intval.lo;
+ escan = escan->data.diadic.left;
+ }
+
+ if (ENODE_IS(escan, EINTCONST)) {
+ CInt64 v = escan->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ vec->us[0] = (UInt16) v.lo;
+ } else {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_VECTOR_UINT:
+ case STRUCT_VECTOR_SINT:
+ case STRUCT_VECTOR_BINT:
+ if (i < 3) {
+ PPCError_Error(PPCErrorStr110, type, 0);
+ } else if (i > 3) {
+ PPCError_Error(PPCErrorStr111, type, 0);
+ } else {
+ escan = expr;
+ i = 3;
+ while (ENODE_IS(escan, ECOMMA)) {
+ CInt64 v;
+ expr = escan->data.diadic.right;
+ v = expr->data.intval;
+ if (!ENODE_IS(expr, EINTCONST)) {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+
+ vec->ul[i--] = expr->data.intval.lo;
+ escan = escan->data.diadic.left;
+ }
+
+ if (ENODE_IS(escan, EINTCONST)) {
+ CInt64 v = escan->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ vec->ul[0] = v.lo;
+ } else {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_VECTOR_FLOAT:
+ if (i < 3) {
+ PPCError_Error(PPCErrorStr110, type, 0);
+ } else if (i > 3) {
+ PPCError_Error(PPCErrorStr111, type, 0);
+ } else {
+ Float fv;
+ escan = expr;
+ i = 3;
+ while (ENODE_IS(escan, ECOMMA)) {
+ expr = escan->data.diadic.right;
+ if (ENODE_IS(expr, EFLOATCONST)) {
+ fv = expr->data.floatval;
+ } else if (ENODE_IS(escan->data.diadic.right, EINTCONST)) {
+ fv = CMach_CalcFloatConvertFromInt(expr->rtype,
+ expr->data.intval);
+ } else {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+
+ CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]);
+ i--;
+ escan = escan->data.diadic.left;
+ }
+
+ if (ENODE_IS(escan, EFLOATCONST)) {
+ fv = escan->data.floatval;
+ } else if (ENODE_IS(escan, EINTCONST)) {
+ fv = CMach_CalcFloatConvertFromInt(escan->rtype, escan->data.intval);
+ } else {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+
+ CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]);
+ result = 1;
+ }
+ break;
+ }
+ } else if (ENODE_IS(expr, EINTCONST)) {
+ int i = 0;
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_VECTOR_UCHAR:
+ case STRUCT_VECTOR_SCHAR:
+ case STRUCT_VECTOR_BCHAR:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UCHAR) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ while (i < 16)
+ vec->uc[i++] = (UInt8) v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_VECTOR_USHORT:
+ case STRUCT_VECTOR_SSHORT:
+ case STRUCT_VECTOR_BSHORT:
+ case STRUCT_VECTOR_PIXEL:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_USHORT || TYPE_STRUCT(type)->stype == STRUCT_VECTOR_PIXEL) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ while (i < 8)
+ vec->us[i++] = (UInt16) v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_VECTOR_UINT:
+ case STRUCT_VECTOR_SINT:
+ case STRUCT_VECTOR_BINT:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_VECTOR_UINT) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(PPCErrorStr113, type, 0);
+ }
+ }
+ while (i < 4)
+ vec->ul[i++] = v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_VECTOR_FLOAT:
+ {
+ Float fv;
+ if (!CInt64_IsInRange(expr->data.intval, 4)) {
+ PPCError_Error(PPCErrorStr112);
+ break;
+ }
+ fv = CMach_CalcFloatConvertFromInt(expr->rtype, expr->data.intval);
+ for (; i < 4; i++)
+ CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i]);
+ result = 1;
+ break;
+ }
+ default:
+ PPCError_Error(PPCErrorStr112);
+ }
+ } else if (ENODE_IS(expr, EFLOATCONST)) {
+ switch (TYPE_STRUCT(type)->stype) {
+ default:
+ PPCError_Error(PPCErrorStr112);
+ break;
+ case STRUCT_VECTOR_FLOAT:
+ {
+ Float fv;
+ i = 0;
+ fv = expr->data.floatval;
+ CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[0]);
+ while (i < 4)
+ CMach_InitFloatMem(TYPE(&stfloat), fv, &vec->f[i++]);
+ result = 1;
+ break;
+ }
+ }
+ } else if (ENODE_IS2(expr, EINDIRECT, EFUNCCALL)) {
+ if (!IS_TYPE_STRUCT(expr->rtype))
+ PPCError_Error(PPCErrorStr112);
+ } else if (!ENODE_IS(expr, EVECTOR128CONST)) {
+ PPCError_Error(PPCErrorStr112);
+ }
+
+ return result;
+}
+
+void CodeGen_InsertSpecialMacros(void) {
+ char *str;
+
+ CPrep_InsertSpecialMacro(&vecM, "__VEC__");
+ CPrep_InsertSpecialMacro(&altivecM, "__ALTIVEC__");
+ CPrep_InsertSpecialMacro(&powcM, "powerc");
+ CPrep_InsertSpecialMacro(&__powcM, "__powerc");
+ CPrep_InsertSpecialMacro(&hostM, "__POWERPC__");
+ CPrep_InsertSpecialMacro(&_ppc_M, "__ppc__");
+
+ CPrep_InsertSpecialMacro(&bendM, "__BIG_ENDIAN__");
+
+ if ((str = CMach_GetCPU()))
+ CPrep_InsertSpecialMacro(&ppc_cpu, str);
+
+ CPrep_InsertSpecialMacro(&profM, "__profile__");
+ CPrep_InsertSpecialMacro(&longI, "__fourbyteints__");
+ CPrep_InsertSpecialMacro(&IEEED, "__IEEEdoubles__");
+ CPrep_InsertSpecialMacro(&macM2, "__MACOS__");
+ CPrep_InsertSpecialMacro(&appleM, "__APPLE__");
+ CPrep_InsertSpecialMacro(&_machM, "__MACH__");
+ CPrep_InsertSpecialMacro(&archM, "__ARCHITECTURE__");
+
+ if (copts.optimizationlevel > 0)
+ CPrep_InsertSpecialMacro(&optM, "__OPTIMIZE__");
+
+ if (copts.codegen_dynamic)
+ CPrep_InsertSpecialMacro(&dynM, "__DYNAMIC__");
+ if (!copts.codegen_dynamic)
+ CPrep_InsertSpecialMacro(&dynM, "__STATIC__");
+
+ if (copts.oldalignment && copts.structalignment == AlignMode2_PPC)
+ CPrep_InsertSpecialMacro(&alignM, "__NATURAL_ALIGNMENT__");
+
+ if (!copts.ANSIstrict)
+ CPrep_InsertSpecialMacro(&ppcM, "ppc");
+}
+
+char *CodeGen_ExpandSpecialMacro(Macro *macro) {
+ if (macro == &vecM) return "10205";
+ if (macro == &altivecM) return "100000000";
+ if (macro == &powcM) return "1";
+ if (macro == &__powcM) return "1";
+ if (macro == &hostM) return "1";
+ if (macro == &bendM) return "1";
+ if (macro == &_ppc_M) return "1";
+ if (CMach_GetCPU() && macro == &ppc_cpu) return "1";
+ if (macro == &profM) return copts.profile ? "1" : "0";
+ if (macro == &longI) return "1";
+ if (macro == &IEEED) return "1";
+ if (macro == &macM2) return "1";
+ if (macro == &appleM) return "1";
+ if (macro == &alignM) return "1";
+
+ if (macro == &optM) {
+ switch (copts.optimizationlevel) {
+ case 1: return "1";
+ case 2: return "2";
+ case 3: return "3";
+ case 4: return "4";
+ case 0: return "0";
+ default: return "9";
+ }
+ }
+
+ if (macro == &_machM) return "1";
+ if (macro == &archM) return "ppc";
+ if (macro == &dynM) return "1";
+ if (!copts.ANSIstrict && macro == &ppcM) return "1";
+ if (macro == &_ppc_M) return "1";
+
+ CError_FATAL(4801);
+ return "0";
+}
+
+void CodeGen_reportheapinfo(Boolean release_flag, char *name, char *text) {
+ HeapInfo o;
+ HeapInfo all;
+
+ CTool_GetHeapInfo(&o, 3);
+ CTool_GetHeapInfo(&all, 5);
+
+ if (release_flag)
+ releaseoheap();
+
+ PPCError_Message(
+ "%n:%u HEAP STATUS\n"
+ " optimizer: %i blocks, used: %i, free: %i, total: %i, largest free: %i\n"
+ " all: %i blocks, used: %i, free: %i, total: %i, largest free: %i",
+ name, text,
+ o.blocks, o.total_size - o.total_free, o.total_free, o.total_size, o.largest_free_block,
+ all.blocks, all.total_size - all.total_free, all.total_free, all.total_size, all.largest_free_block
+ );
+}
+
+static void CodeGen_heaperror(void) {
+ CodeGen_reportheapinfo(1, "?", "out of memory");
+ if (saveheaperror) {
+ setheaperror(saveheaperror);
+ saveheaperror();
+ }
+}
+
+void CodeGen_InitialSanityCheck(void) {
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c
new file mode 100644
index 0000000..14627cf
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c
@@ -0,0 +1,857 @@
+#include "compiler/Exceptions.h"
+#include "compiler/CError.h"
+#include "compiler/CException.h"
+#include "compiler/CInit.h"
+#include "compiler/CFunc.h"
+#include "compiler/CParser.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/objects.h"
+
+static PCAction *pc_actions;
+static PCAction *last_pc_action;
+EANode *DAG[EAT_NACTIONS];
+static GList exceptmodule;
+static OLinkList *except_refs;
+static OLinkList *last_except_ref;
+
+static EANode *makeEAnode(ExceptionAction *ea) {
+ EANode *prev;
+ EANode *node;
+
+ for (node = DAG[ea->type]; node; node = node->dagListNext) {
+ if (node->action == ea)
+ return node;
+ }
+
+ if (ea->prev)
+ prev = makeEAnode(ea->prev);
+ else
+ prev = NULL;
+
+ for (node = DAG[ea->type]; node; node = node->dagListNext) {
+ if (node->prev == prev && CExcept_ActionCompare(node->action, ea))
+ return node;
+ }
+
+ node = lalloc(sizeof(EANode));
+ node->prev = prev;
+ node->action = ea;
+ node->count = 0;
+ node->xE = 0;
+
+ node->dagListNext = DAG[ea->type];
+ DAG[ea->type] = node;
+
+ if (prev)
+ prev->count++;
+ return node;
+}
+
+static void addrelocation(Object *obj, SInt32 offset) {
+ OLinkList *ref;
+
+ ref = lalloc(sizeof(OLinkList));
+ ref->next = NULL;
+ ref->obj = obj;
+ ref->offset = offset;
+ ref->somevalue = 0;
+ if (except_refs)
+ last_except_ref->next = ref;
+ else
+ except_refs = ref;
+ last_except_ref = ref;
+}
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct AABC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt32 d;
+} AABC;
+
+typedef struct AACC {
+ UInt8 a;
+ UInt8 b;
+ UInt32 c;
+ UInt32 d;
+} AACC;
+
+typedef struct AABBC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt16 d;
+ UInt32 e;
+} AABBC;
+
+typedef struct AABCC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt32 d;
+ UInt32 e;
+} AABCC;
+
+typedef struct AACCC {
+ UInt8 a;
+ UInt8 b;
+ UInt32 c;
+ UInt32 d;
+ UInt32 e;
+} AACCC;
+
+typedef struct AABBBC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt16 d;
+ UInt16 e;
+ UInt32 f;
+} AABBBC;
+
+typedef struct AABBCC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt16 d;
+ UInt32 e;
+ UInt32 f;
+} AABBCC;
+
+typedef struct AACCCC {
+ UInt8 a;
+ UInt8 b;
+ UInt32 c;
+ UInt32 d;
+ UInt32 e;
+ UInt32 f;
+} AACCCC;
+
+typedef struct AABCCCC {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+ UInt32 d;
+ UInt32 e;
+ UInt32 f;
+ UInt32 g;
+} AABCCCC;
+
+typedef struct AACCCCC {
+ UInt8 a;
+ UInt8 b;
+ UInt32 c;
+ UInt32 d;
+ UInt32 e;
+ UInt32 f;
+ UInt32 g;
+} AACCCCC;
+
+typedef struct AAB {
+ UInt8 a;
+ UInt8 b;
+ UInt16 c;
+} AAB;
+
+typedef struct AAC {
+ UInt8 a;
+ UInt8 b;
+ UInt32 c;
+} AAC;
+
+typedef struct AA {
+ UInt8 a;
+ UInt8 b;
+} AA;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static void allocateactioninfo(EANode *node) {
+ ExceptionAction *ea;
+ SInt32 offset;
+ UInt32 flag26;
+ int reg;
+ int reg2;
+
+ while (node && (node->xE == 0 || node->prev == NULL)) {
+ offset = exceptmodule.size;
+ if (node->xE == 0)
+ node->xE = offset;
+
+ flag26 = node->prev ? 0 : 0x80;
+
+ ea = node->action;
+
+ switch (ea->type) {
+ case EAT_NOP:
+ CError_FATAL(146);
+ break;
+ case EAT_DESTROYLOCAL: {
+ if (local_is_16bit_offset(ea->data.destroy_local.local)) {
+ AABC e;
+ e.a = flag26 | 2;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local.local));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local.dtor, offset + 4);
+ } else {
+ AACC e;
+ e.a = flag26 | 0x11;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local.local));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local.dtor, offset + 6);
+ }
+ break;
+ }
+ case EAT_DESTROYLOCALCOND: {
+ reg = OBJECT_REG(ea->data.destroy_local_cond.cond);
+ if (
+ (reg || local_is_16bit_offset(ea->data.destroy_local_cond.cond)) &&
+ local_is_16bit_offset(ea->data.destroy_local_cond.local)
+ )
+ {
+ AABBC e;
+ e.a = flag26 | 3;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_cond.cond));
+ e.d = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_cond.local));
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_cond.dtor, offset + 6);
+ } else {
+ AACCC e;
+ e.a = flag26 | 0x12;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_cond.cond));
+ e.d = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_cond.local));
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_cond.dtor, offset + 10);
+ }
+ break;
+ }
+ case EAT_DESTROYLOCALOFFSET: {
+ if (local_is_16bit_offset(ea->data.destroy_local_offset.local)) {
+ AABC e;
+ e.a = flag26 | 2;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(ea->data.destroy_local_offset.offset + local_offset_16(ea->data.destroy_local_offset.local));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_offset.dtor, offset + 4);
+ } else {
+ AACC e;
+ e.a = flag26 | 0x11;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord32(ea->data.destroy_local_offset.offset + local_offset_32(ea->data.destroy_local_offset.local));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_offset.dtor, offset + 6);
+ }
+ break;
+ }
+ case EAT_DESTROYLOCALPOINTER: {
+ reg = OBJECT_REG(ea->data.destroy_local_pointer.pointer);
+ if (reg || local_is_16bit_offset(ea->data.destroy_local_pointer.pointer)) {
+ AABC e;
+ e.a = flag26 | 4;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_pointer.pointer));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_pointer.dtor, offset + 4);
+ } else {
+ AACC e;
+ e.a = flag26 | 0x13;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_pointer.pointer));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_pointer.dtor, offset + 6);
+ }
+ break;
+ }
+ case EAT_DESTROYLOCALARRAY: {
+ if (local_is_16bit_offset(ea->data.destroy_local_array.localarray)) {
+ AABBBC e;
+ e.a = flag26 | 5;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_array.localarray));
+ e.d = CTool_EndianConvertWord16(ea->data.destroy_local_array.elements);
+ e.e = CTool_EndianConvertWord16(ea->data.destroy_local_array.element_size);
+ e.f = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_array.dtor, offset + 8);
+ } else {
+ AACCCC e;
+ e.a = flag26 | 0x14;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_array.localarray));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_local_array.elements);
+ e.e = CTool_EndianConvertWord32(ea->data.destroy_local_array.element_size);
+ e.f = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_local_array.dtor, offset + 14);
+ }
+ break;
+ }
+ case EAT_DESTROYMEMBER: {
+ reg = OBJECT_REG(ea->data.destroy_member.objectptr);
+ if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) {
+ AABCC e;
+ e.a = flag26 | 7;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset);
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member.dtor, offset + 8);
+ } else {
+ AACCC e;
+ e.a = flag26 | 0x16;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset);
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member.dtor, offset + 10);
+ }
+ break;
+ }
+ case EAT_DESTROYBASE: {
+ reg = OBJECT_REG(ea->data.destroy_member.objectptr);
+ if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) {
+ AABCC e;
+ e.a = flag26 | 6;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset);
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member.dtor, offset + 8);
+ } else {
+ AACCC e;
+ e.a = flag26 | 0x15;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset);
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member.dtor, offset + 10);
+ }
+ break;
+ }
+ case EAT_DESTROYMEMBERCOND: {
+ reg = OBJECT_REG(ea->data.destroy_member_cond.cond);
+ reg2 = OBJECT_REG(ea->data.destroy_member_cond.objectptr);
+ if (
+ (reg || local_is_16bit_offset(ea->data.destroy_member_cond.cond)) &&
+ (reg2 || local_is_16bit_offset(ea->data.destroy_member_cond.objectptr))
+ )
+ {
+ AABBCC e;
+ e.a = flag26 | 8;
+ e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6);
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_cond.cond));
+ e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.destroy_member_cond.objectptr));
+ e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset);
+ e.f = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member_cond.dtor, offset + 10);
+ } else {
+ AACCCC e;
+ e.a = flag26 | 0x17;
+ e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6);
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_cond.cond));
+ e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.destroy_member_cond.objectptr));
+ e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset);
+ e.f = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member_cond.dtor, offset + 14);
+ }
+ break;
+ }
+ case EAT_DESTROYMEMBERARRAY: {
+ reg = OBJECT_REG(ea->data.destroy_member_array.objectptr);
+ if (reg || local_is_16bit_offset(ea->data.destroy_member_array.objectptr)) {
+ AABCCCC e;
+ e.a = flag26 | 9;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_array.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset);
+ e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements);
+ e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size);
+ e.g = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member_array.dtor, offset + 16);
+ } else {
+ AACCCCC e;
+ e.a = flag26 | 0x18;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_array.objectptr));
+ e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset);
+ e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements);
+ e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size);
+ e.g = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.destroy_member_array.dtor, offset + 18);
+ }
+ break;
+ }
+ case EAT_DELETEPOINTER:
+ case EAT_DELETELOCALPOINTER: {
+ reg = OBJECT_REG(ea->data.delete_pointer.pointerobject);
+ if (reg || local_is_16bit_offset(ea->data.delete_pointer.pointerobject)) {
+ AABC e;
+ e.a = flag26 | 0xA;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer.pointerobject));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.delete_pointer.deletefunc, offset + 4);
+ } else {
+ AACC e;
+ e.a = flag26 | 0x19;
+ e.b = (reg != 0) << 7;
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer.pointerobject));
+ e.d = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.delete_pointer.deletefunc, offset + 6);
+ }
+ break;
+ }
+ case EAT_DELETEPOINTERCOND: {
+ reg = OBJECT_REG(ea->data.delete_pointer_cond.cond);
+ reg2 = OBJECT_REG(ea->data.delete_pointer_cond.pointerobject);
+ if (
+ (reg || local_is_16bit_offset(ea->data.delete_pointer_cond.cond)) &&
+ (reg2 || local_is_16bit_offset(ea->data.delete_pointer_cond.pointerobject))
+ )
+ {
+ AABBC e;
+ e.a = flag26 | 0xB;
+ e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6);
+ e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer_cond.cond));
+ e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.delete_pointer_cond.pointerobject));
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 6);
+ } else {
+ AACCC e;
+ e.a = flag26 | 0x1A;
+ e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6);
+ e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer_cond.cond));
+ e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.delete_pointer_cond.pointerobject));
+ e.e = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 10);
+ }
+ break;
+ }
+ case EAT_CATCHBLOCK: {
+ AACCC e;
+ e.a = flag26 | 0x10;
+ e.b = 0;
+ e.c = 0;
+ if (ea->data.catch_block.catch_label->pclabel)
+ e.d = CTool_EndianConvertWord32(ea->data.catch_block.catch_label->pclabel->block->codeOffset);
+ else
+ e.d = 0;
+ e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.catch_block.catch_info_object));
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ if (ea->data.catch_block.catch_typeid)
+ addrelocation(ea->data.catch_block.catch_typeid, offset + 2);
+ break;
+ }
+ case EAT_ACTIVECATCHBLOCK: {
+ if (local_is_16bit_offset(ea->data.active_catch_block.catch_info_object)) {
+ AAB e;
+ e.a = flag26 | 0xD;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.active_catch_block.catch_info_object));
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ } else {
+ AAC e;
+ e.a = flag26 | 0x1B;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.active_catch_block.catch_info_object));
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ }
+ break;
+ }
+ case EAT_SPECIFICATION: {
+ AABCC e;
+ int i;
+
+ e.a = flag26 | 0xF;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(ea->data.specification.unexp_ids);
+ if (ea->data.specification.unexp_label->pclabel)
+ e.d = CTool_EndianConvertWord32(ea->data.specification.unexp_label->pclabel->block->codeOffset);
+ e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.specification.unexp_info_object));
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+
+ for (i = 0; i < ea->data.specification.unexp_ids; i++) {
+ addrelocation(ea->data.specification.unexp_id[i], 12 + i * 4 + offset);
+ AppendGListLong(&exceptmodule, 0);
+ }
+ break;
+ }
+ case EAT_TERMINATE: {
+ AA e;
+ e.a = flag26 | 0xE;
+ e.b = 0;
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ break;
+ }
+ default:
+ CError_FATAL(671);
+ }
+
+ node = node->prev;
+ }
+
+ if (node) {
+ AAB e;
+ e.a = 1;
+ e.b = 0;
+ e.c = CTool_EndianConvertWord16(node->xE);
+ AppendGListData(&exceptmodule, &e, sizeof(e));
+ }
+}
+
+static UInt32 findPC(PCode *instr) {
+ UInt32 pc = instr->block->codeOffset;
+ instr = instr->prevPCode;
+ while (instr) {
+ instr = instr->prevPCode;
+ pc += 4;
+ }
+ CError_ASSERT(704, FITS_IN_USHORT(pc));
+ return pc;
+}
+
+static UInt32 findPC_long(PCode *instr) {
+ UInt32 pc = instr->block->codeOffset;
+ instr = instr->prevPCode;
+ while (instr) {
+ instr = instr->prevPCode;
+ pc += 4;
+ }
+ return pc;
+}
+
+void initializeexceptiontables(void) {
+ int i;
+
+ for (i = 0; i < EAT_NACTIONS; i++)
+ DAG[i] = NULL;
+
+ pc_actions = last_pc_action = NULL;
+ except_refs = last_except_ref = NULL;
+}
+
+int countexceptionactionregisters(ExceptionAction *actions) {
+ int count = 0;
+
+ while (actions) {
+ switch (actions->type) {
+ case EAT_DESTROYLOCALCOND:
+ if (OBJECT_REG(actions->data.destroy_local_cond.cond))
+ count++;
+ break;
+ case EAT_DESTROYLOCALPOINTER:
+ if (OBJECT_REG(actions->data.destroy_local_pointer.pointer))
+ count++;
+ break;
+ case EAT_DESTROYMEMBER:
+ if (OBJECT_REG(actions->data.destroy_member.objectptr))
+ count++;
+ break;
+ case EAT_DESTROYBASE:
+ if (OBJECT_REG(actions->data.destroy_base.objectptr))
+ count++;
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ if (OBJECT_REG(actions->data.destroy_member_cond.cond))
+ count++;
+ if (OBJECT_REG(actions->data.destroy_member_cond.objectptr))
+ count++;
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ if (OBJECT_REG(actions->data.destroy_member_array.objectptr))
+ count++;
+ break;
+ case EAT_DELETEPOINTER:
+ case EAT_DELETELOCALPOINTER:
+ if (OBJECT_REG(actions->data.delete_pointer.pointerobject))
+ count++;
+ break;
+ case EAT_DELETEPOINTERCOND:
+ if (OBJECT_REG(actions->data.delete_pointer_cond.cond))
+ count++;
+ if (OBJECT_REG(actions->data.delete_pointer_cond.pointerobject))
+ count++;
+ break;
+ }
+ actions = actions->prev;
+ }
+
+ return count;
+}
+
+void noteexceptionactionregisters(ExceptionAction *actions, PCodeArg *ops) {
+ Object *obj;
+ int reg;
+
+ while (actions) {
+ switch (actions->type) {
+ case EAT_DESTROYLOCALCOND:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_local_cond.cond))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DESTROYLOCALPOINTER:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_local_pointer.pointer))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DESTROYMEMBER:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_member.objectptr))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DESTROYBASE:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_base.objectptr))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.cond))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.objectptr))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ if ((reg = OBJECT_REG(obj = actions->data.destroy_member_array.objectptr))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DELETEPOINTER:
+ case EAT_DELETELOCALPOINTER:
+ if ((reg = OBJECT_REG(obj = actions->data.delete_pointer.pointerobject))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ case EAT_DELETEPOINTERCOND:
+ if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.cond))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.pointerobject))) {
+ ops->kind = PCOp_REGISTER;
+ ops->arg = obj->u.var.info->rclass;
+ ops->data.reg.reg = reg;
+ ops->data.reg.effect = EffectRead | Effect8;
+ ops++;
+ }
+ break;
+ }
+ actions = actions->prev;
+ }
+}
+
+void recordexceptionactions(PCode *instr, ExceptionAction *actions) {
+ PCAction *pca;
+
+ if (!actions && (!last_pc_action || !last_pc_action->actions))
+ return;
+
+ pca = lalloc(sizeof(PCAction));
+ pca->next = NULL;
+ pca->firstInstr = pca->lastInstr = instr;
+ pca->actions = actions;
+ pca->prev = last_pc_action;
+ if (last_pc_action)
+ last_pc_action->next = pca;
+ else
+ pc_actions = pca;
+ last_pc_action = pca;
+
+ branch_label(makepclabel());
+ while (actions) {
+ if (actions->type == EAT_CATCHBLOCK && actions->data.catch_block.catch_label->pclabel)
+ pcbranch(instr->block, actions->data.catch_block.catch_label->pclabel);
+ else if (actions->type == EAT_SPECIFICATION && actions->data.specification.unexp_label->pclabel)
+ pcbranch(instr->block, actions->data.specification.unexp_label->pclabel);
+ actions = actions->prev;
+ }
+}
+
+static void deleteexceptionaction(PCAction *pca) {
+ if (pca->prev)
+ pca->prev->next = pca->next;
+ else
+ pc_actions = pca->next;
+
+ if (pca->next)
+ pca->next->prev = pca->prev;
+}
+
+static int mergeexceptionactions(void) {
+ int count;
+ PCAction *pca;
+ PCAction *prev;
+
+ if (!pc_actions)
+ return 0;
+
+ for (pca = pc_actions; pca; pca = pca->next) {
+ if (pca->firstInstr->block->flags & fDeleted)
+ deleteexceptionaction(pca);
+ }
+
+ if (!(pca = pc_actions))
+ return 0;
+
+ while (pca) {
+ pca->node = pca->actions ? makeEAnode(pca->actions) : NULL;
+ pca = pca->next;
+ }
+
+ prev = pc_actions;
+ for (pca = pc_actions->next; pca; pca = pca->next) {
+ if (pca->node == prev->node) {
+ prev->lastInstr = pca->lastInstr;
+ deleteexceptionaction(pca);
+ } else {
+ prev = pca;
+ }
+ }
+
+ count = 0;
+ for (pca = pc_actions; pca; pca = pca->next) {
+ if (!pca->actions)
+ deleteexceptionaction(pca);
+ else
+ count++;
+ }
+
+ return count;
+}
+
+typedef struct ExceptionThing {
+ UInt32 x0;
+ UInt16 x4;
+ UInt16 x6;
+} ExceptionThing;
+
+void dumpexceptiontables(Object *function, SInt32 codesize) {
+ PCAction *pca;
+ UInt32 insn_start;
+ UInt32 insn_count;
+ UInt16 *sh;
+ ExceptionThing *thing;
+ int count;
+
+ count = mergeexceptionactions();
+ InitGList(&exceptmodule, 256);
+ AppendGListNoData(&exceptmodule, 8 * count + 4);
+ AppendGListLong(&exceptmodule, 0);
+
+ for (pca = pc_actions; pca; pca = pca->next) {
+ if (pca->node->count == 0 && pca->node->xE == 0)
+ allocateactioninfo(pca->node);
+ }
+
+ sh = (UInt16 *) *exceptmodule.data;
+ if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) {
+ sh[0] =
+ CTool_EndianConvertWord16(
+ (used_nonvolatile_registers[RegClass_GPR] << 11) |
+ ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) |
+ (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) |
+ ((dynamic_stack & 1) << 4) |
+ 8);
+ sh[0] |= 4;
+ if (copts.altivec_vrsave)
+ sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] << 11) | 0x400);
+ else
+ sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] & 0x1F) << 11);
+ } else {
+ sh[0] =
+ CTool_EndianConvertWord16(
+ (used_nonvolatile_registers[RegClass_GPR] << 11) |
+ ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) |
+ (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) |
+ ((dynamic_stack & 1) << 4) |
+ 8);
+ sh[1] = 0;
+ }
+
+ thing = (ExceptionThing *) (sh + 2);
+ pca = pc_actions;
+ while (pca) {
+ insn_start = findPC_long(pca->firstInstr);
+ insn_count = (findPC_long(pca->lastInstr) - insn_start) / 4;
+ CError_ASSERT(1203, (insn_count & 0xFFFF0000) == 0);
+ thing->x0 = CTool_EndianConvertWord32(insn_start + 4);
+ thing->x4 = CTool_EndianConvertWord16(insn_count);
+ thing->x6 = CTool_EndianConvertWord16(pca->node->xE);
+ pca = pca->next;
+ thing++;
+ }
+
+ LockGList(&exceptmodule);
+ ObjGen_DeclareExceptionTables(function, codesize, *exceptmodule.data, exceptmodule.size, except_refs);
+ FreeGList(&exceptmodule);
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c
new file mode 100644
index 0000000..67d7443
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/FunctionCalls.c
@@ -0,0 +1,642 @@
+#include "compiler/FunctionCalls.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/InstrSelection.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Registers.h"
+#include "compiler/StackFrame.h"
+#include "compiler/StructMoves.h"
+#include "compiler/types.h"
+
+enum {
+ AIF_PassInGPR = 1,
+ AIF_PassInFPR = 2,
+ AIF_PassOnStack = 4,
+ AIF_ExtendTo32Bits = 8,
+ AIF_ForceDoublePrecision = 0x10,
+ AIF_PassInVR = 0x20,
+ AIF_PassMask = AIF_PassInGPR | AIF_PassInFPR | AIF_PassOnStack | AIF_PassInVR
+};
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct ArgInfo {
+ struct ArgInfo *next;
+ ENode *expr;
+ Operand opnd;
+ SInt32 offset;
+ short gpr;
+ short gprHi;
+ short fpr;
+ short vr;
+ short evaluated;
+ short flags;
+} ArgInfo;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+// forward decls
+static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs);
+
+static ArgInfo *make_arginfo(ENode *expr) {
+ ArgInfo *info = lalloc(sizeof(ArgInfo));
+ memclrw(info, sizeof(ArgInfo));
+
+ info->next = NULL;
+ info->expr = expr;
+ info->offset = -1;
+ info->gpr = -1;
+ info->gprHi = -1;
+ info->fpr = -1;
+ info->vr = -1;
+ info->evaluated = 0;
+ info->flags = 0;
+
+ return info;
+}
+
+static ArgInfo *analyze_arguments(ENode *funcref, ENodeList *arg_expr, FuncArg *arg, UInt32 *used_regs, Boolean *resultHasFloats, char has_varargs) {
+ ArgInfo *infos;
+ ArgInfo *info;
+ SInt32 displ;
+ SInt32 arg_size;
+ int gpr_counter;
+ int fpr_counter;
+ int vr_counter;
+ Type *type;
+ RegClass rclass;
+ Boolean spilledVectorFlag;
+
+ infos = NULL;
+ displ = 0;
+ gpr_counter = 3;
+ fpr_counter = 1;
+ vr_counter = 2;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ used_regs[rclass] = 0;
+ *resultHasFloats = 0;
+
+ while (arg_expr) {
+ if (arg_expr->node == funcref) {
+ arg_expr = arg_expr->next;
+ arg = arg->next;
+ continue;
+ }
+
+ type = arg_expr->node->rtype;
+ if (infos) {
+ info->next = make_arginfo(arg_expr->node);
+ info = info->next;
+ } else {
+ infos = info = make_arginfo(arg_expr->node);
+ }
+
+ arg_size = 0;
+ if (IS_TYPE_VECTOR(type)) {
+ if (arg == &elipsis) {
+ spilledVectorFlag = 1;
+ info->flags |= AIF_PassOnStack;
+ } else {
+ spilledVectorFlag = 0;
+ if (vr_counter <= 13) {
+ info->flags |= AIF_PassInVR;
+ info->vr = vr_counter;
+ used_regs[RegClass_VR] |= 1 << vr_counter;
+ } else {
+ spilledVectorFlag = 1;
+ info->flags |= AIF_PassOnStack;
+ }
+ }
+
+ if (has_varargs) {
+ if (gpr_counter < 10) {
+ gpr_counter = ((gpr_counter - 2) & ~3) + 5;
+ if (arg == &elipsis && gpr_counter < 10) {
+ info->flags |= AIF_PassInGPR;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= (15 << gpr_counter) & 0x7E0;
+ }
+ gpr_counter += 4;
+ }
+ spilledVectorFlag = 1;
+ }
+
+ if (spilledVectorFlag)
+ arg_size = 16;
+ vr_counter++;
+ } else if (IS_TYPE_FLOAT(type)) {
+ *resultHasFloats = 1;
+ if (!arg || arg == &oldstyle) {
+ if (fpr_counter <= 13) {
+ info->flags |= AIF_PassInFPR;
+ info->fpr = fpr_counter;
+ used_regs[RegClass_FPR] |= 1 << fpr_counter;
+ } else {
+ info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision;
+ }
+ arg_size = 8;
+ fpr_counter++;
+ gpr_counter += 2;
+ } else if (arg == &elipsis) {
+ if (gpr_counter < 10) {
+ info->flags |= AIF_PassInGPR;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= 3 << gpr_counter;
+ } else if (gpr_counter == 10) {
+ info->flags |= AIF_PassInGPR | AIF_PassOnStack | AIF_ForceDoublePrecision;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= 3 << gpr_counter;
+ } else {
+ info->flags |= AIF_PassOnStack | AIF_ForceDoublePrecision;
+ }
+ arg_size = 8;
+ fpr_counter++;
+ gpr_counter += 2;
+ } else {
+ if (fpr_counter <= 13) {
+ info->flags |= AIF_PassInFPR;
+ info->fpr = fpr_counter;
+ used_regs[RegClass_FPR] |= 1 << fpr_counter;
+ } else {
+ info->flags |= AIF_PassOnStack;
+ }
+
+ if (type->size == 4) {
+ arg_size = 4;
+ gpr_counter++;
+ } else {
+ arg_size = 8;
+ gpr_counter += 2;
+ }
+
+ fpr_counter++;
+ }
+ } else if (TYPE_IS_8BYTES(type)) {
+ if (gpr_counter <= 10) {
+ info->flags |= AIF_PassInGPR;
+ if (copts.littleendian) {
+ info->gpr = gpr_counter;
+ info->gprHi = gpr_counter + 1;
+ } else {
+ info->gpr = gpr_counter + 1;
+ info->gprHi = gpr_counter;
+ }
+ used_regs[RegClass_GPR] |= 1 << gpr_counter;
+ if ((gpr_counter + 1) <= 10)
+ used_regs[RegClass_GPR] |= 1 << (gpr_counter + 1);
+ } else {
+ info->flags |= AIF_PassOnStack;
+ }
+
+ arg_size = 8;
+ gpr_counter += 2;
+ } else if (TYPE_FITS_IN_REGISTER(type)) {
+ if ((!arg || arg == &elipsis || arg == &oldstyle) && type->size < 4)
+ info->flags |= AIF_ExtendTo32Bits;
+
+ if (gpr_counter <= 10) {
+ info->flags |= AIF_PassInGPR;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= 1 << gpr_counter;
+ } else {
+ info->flags |= AIF_PassOnStack;
+ }
+
+ arg_size = 4;
+ gpr_counter++;
+ } else if (IS_TYPE_ARRAY(type) || IS_TYPE_NONVECTOR_STRUCT(type) || IS_TYPE_CLASS(type) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(type)) {
+ SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0);
+ if (gpr_counter <= 10) {
+ if ((gpr_counter + gprs_needed - 1) <= 10) {
+ info->flags |= AIF_PassInGPR;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= ((1 << gprs_needed) - 1) << gpr_counter;
+ } else {
+ info->flags |= AIF_PassInGPR | AIF_PassOnStack;
+ info->gpr = gpr_counter;
+ used_regs[RegClass_GPR] |= ((1 << (11 - gpr_counter)) - 1) << gpr_counter;
+ }
+ } else {
+ info->flags |= AIF_PassOnStack;
+ }
+
+ gpr_counter += gprs_needed;
+ arg_size = type->size;
+ } else {
+ CError_FATAL(421);
+ }
+
+ displ = set_out_param_displ(displ, type, info->flags & AIF_PassOnStack, &info->offset, arg_size);
+
+ arg_expr = arg_expr->next;
+ if (arg && arg != &elipsis && arg != &oldstyle)
+ arg = arg->next;
+ }
+
+ update_out_param_size(displ);
+
+ return infos;
+}
+
+static void pass_in_memory(ArgInfo *info) {
+ Type *type;
+ Operand opnd;
+
+ type = info->expr->rtype;
+ memclrw(&opnd, sizeof(Operand));
+
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ if (TYPE_IS_8BYTES(type)) {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+ coerce_to_register_pair(&info->opnd, type, 0, 0);
+
+ load_store_register(
+ PC_STW, info->opnd.reg, 1,
+ NULL, low_offset + out_param_displ_to_offset(info->offset));
+ load_store_register(
+ PC_STW, info->opnd.regHi, 1,
+ NULL, high_offset + out_param_displ_to_offset(info->offset));
+ } else {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+ if (info->flags & AIF_ExtendTo32Bits)
+ extend32(&info->opnd, type, 0);
+ ENSURE_GPR(&info->opnd, type, 0);
+
+ load_store_register(
+ PC_STW, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+ ENSURE_FPR(&info->opnd, type, 0);
+
+ if (type->size == 4 && !(info->flags & AIF_ForceDoublePrecision)) {
+ load_store_register(
+ PC_STFS, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ } else {
+ load_store_register(
+ PC_STFD, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ }
+ } else if (IS_TYPE_VECTOR(type)) {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+ ENSURE_VR(&info->opnd, type, 0);
+
+ load_store_register(
+ PC_STVX, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ } else {
+ opnd.optype = OpndType_IndirectGPR_ImmOffset;
+ opnd.reg = 1;
+ opnd.object = NULL;
+ opnd.immOffset = out_param_displ_to_offset(info->offset);
+
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+
+ move_block(&opnd, &info->opnd, type->size, CMach_ArgumentAlignment(type));
+ }
+}
+
+static void pass_in_register(ArgInfo *info) {
+ Type *type;
+
+ type = info->expr->rtype;
+
+ if ((info->flags & AIF_PassMask) == AIF_PassInFPR) {
+ if (!info->evaluated)
+ GEN_NODE_TO_REG(info->expr, info->fpr, 0, &info->opnd);
+ ENSURE_FPR(&info->opnd, type, info->fpr);
+ if (info->opnd.reg != info->fpr)
+ emitpcode(PC_FMR, info->fpr, info->opnd.reg);
+ } else if ((info->flags & AIF_PassMask) == AIF_PassInVR) {
+ if (!info->evaluated)
+ GEN_NODE_TO_REG(info->expr, info->vr, 0, &info->opnd);
+ ENSURE_VR(&info->opnd, type, info->vr);
+ if (info->opnd.reg != info->vr)
+ emitpcode(PC_VMR, info->vr, info->opnd.reg);
+ } else if (TYPE_FITS_IN_REGISTER(type)) {
+ if (TYPE_IS_8BYTES(type)) {
+ if (!info->evaluated)
+ GEN_NODE_TO_REG(info->expr, info->gpr, info->gprHi, &info->opnd);
+ coerce_to_register_pair(&info->opnd, type, info->gpr, info->gprHi);
+ if (copts.littleendian) {
+ if (info->gprHi > 10) {
+ load_store_register(
+ PC_STW, info->opnd.regHi, 1,
+ NULL, high_offset + out_param_displ_to_offset(info->offset));
+ }
+ } else {
+ if (info->gpr > 10) {
+ load_store_register(
+ PC_STW, info->opnd.reg, 1,
+ NULL, low_offset + out_param_displ_to_offset(info->offset));
+ }
+ }
+ } else {
+ if (!info->evaluated)
+ GEN_NODE_TO_REG(info->expr, info->gpr, 0, &info->opnd);
+ if (info->flags & AIF_ExtendTo32Bits)
+ extend32(&info->opnd, type, info->gpr);
+ ENSURE_GPR(&info->opnd, type, info->gpr);
+ if (info->opnd.reg != info->gpr)
+ emitpcode(PC_MR, info->gpr, info->opnd.reg);
+ }
+ } else if (IS_TYPE_FLOAT(type)) {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+
+ if (type->size != 4 && info->opnd.optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(
+ PC_LWZ, info->gpr, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset);
+ load_store_register(
+ PC_LWZ, info->gpr + 1, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + 4);
+ } else {
+ ENSURE_FPR(&info->opnd, type, 0);
+ load_store_register(
+ PC_STFD, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ load_store_register(
+ PC_LWZ, info->gpr, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ load_store_register(
+ PC_LWZ, info->gpr + 1, 1,
+ NULL, out_param_displ_to_offset(info->offset) + 4);
+ }
+ } else if (IS_TYPE_VECTOR(type)) {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+
+ if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(
+ PC_LWZ, info->gpr, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset);
+ load_store_register(
+ PC_LWZ, info->gpr + 1, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + 4);
+ if ((info->gpr + 2) < 10) {
+ load_store_register(
+ PC_LWZ, info->gpr + 2, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + 8);
+ load_store_register(
+ PC_LWZ, info->gpr + 3, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + 12);
+ }
+ } else {
+ ENSURE_VR(&info->opnd, type, 0);
+ load_store_register(
+ PC_STVX, info->opnd.reg, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ load_store_register(
+ PC_LWZ, info->gpr, 1,
+ NULL, out_param_displ_to_offset(info->offset));
+ load_store_register(
+ PC_LWZ, info->gpr + 1, 1,
+ NULL, out_param_displ_to_offset(info->offset) + 4);
+ if ((info->gpr + 2) < 10) {
+ load_store_register(
+ PC_LWZ, info->gpr + 2, 1,
+ NULL, out_param_displ_to_offset(info->offset) + 8);
+ load_store_register(
+ PC_LWZ, info->gpr + 3, 1,
+ NULL, out_param_displ_to_offset(info->offset) + 12);
+ }
+ }
+ } else {
+ if (!info->evaluated)
+ GEN_NODE(info->expr, &info->opnd);
+
+ if (type->size <= 4) {
+ if (info->opnd.optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(&info->opnd);
+
+ if (info->opnd.optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(
+ PC_LWZ, info->gpr, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset);
+ } else if (info->opnd.optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(
+ PC_LWZX, info->gpr, info->opnd.reg,
+ info->opnd.regOffset);
+ }
+ } else {
+ SInt32 gprs_needed = (type->size >> 2) + ((type->size & 3) != 0);
+ SInt32 i;
+
+ make_addressable(&info->opnd, gprs_needed * 4, 12);
+ for (i = 0; i < gprs_needed; i++) {
+ if (info->opnd.reg != (info->gpr + i)) {
+ load_store_register(
+ PC_LWZ, info->gpr + i, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + i * 4);
+ }
+ }
+
+ if (info->opnd.reg >= info->gpr && info->opnd.reg < (info->gpr + gprs_needed)) {
+ load_store_register(
+ PC_LWZ, info->opnd.reg, info->opnd.reg,
+ info->opnd.object, info->opnd.immOffset + (info->opnd.reg - info->gpr) * 4);
+ }
+ }
+ }
+}
+
+static void pass_in_register_and_memory(ArgInfo *info) {
+ Type *type;
+ int gpr;
+ SInt32 offset;
+
+ type = info->expr->rtype;
+ gpr = info->gpr;
+ offset = 0;
+ while (offset < type->size && gpr <= 10) {
+ load_store_register(
+ PC_LWZ, gpr, 1,
+ NULL, offset + out_param_displ_to_offset(info->offset));
+ gpr++;
+ offset += 4;
+ }
+}
+
+static Boolean needs_TOC_reload(Object *func) {
+ return 0;
+}
+
+static void load_virtual_function(TypeClass *tclass, SInt32 offset, int reg, Operand *opnd) {
+ if (tclass->flags & CLASS_HANDLEOBJECT) {
+ load_store_register(PC_LWZ, 12, reg, NULL, 0);
+ load_store_register(PC_LWZ, 12, 12, NULL, tclass->vtable->offset);
+ } else {
+ load_store_register(PC_LWZ, 12, reg, NULL, tclass->vtable->offset);
+ }
+ load_store_register(PC_LWZ, 12, 12, NULL, offset);
+ opnd->optype = OpndType_GPR;
+ opnd->reg = 12;
+}
+
+static void branch_subroutine_indirect(Object *func, Operand *addrOpnd, UInt32 *used_regs) {
+ if (addrOpnd->reg != 12)
+ emitpcode(PC_MR, 12, addrOpnd->reg);
+
+ used_regs[RegClass_GPR] |= 1 << 12;
+ branch_subroutine(func, 1, used_regs);
+}
+
+static void evaluate_nested_function_calls(ArgInfo *info) {
+ ArgInfo *scan;
+
+ scan = info->next;
+ while (scan && !scan->expr->hascall)
+ scan = scan->next;
+
+ if (scan)
+ evaluate_nested_function_calls(scan);
+
+ if (info->expr->hascall) {
+ GEN_NODE(info->expr, &info->opnd);
+ info->evaluated = 1;
+ }
+}
+
+void call_function(ENode *expr, Operand *output) {
+ ArgInfo *infos; // r31
+ ENode *funcref = expr->data.funccall.funcref; // r27
+ Type *resultType = expr->data.funccall.functype->functype; // r26
+ ENode *node = NULL; // r25
+ char has_varargs; // r24
+ ArgInfo *info; // r22
+ Operand opnd;
+ UInt32 used_regs[RegClassMax] = {0};
+ Boolean has_floats;
+ FuncArg *arg;
+
+ memclrw(&opnd, sizeof(Operand));
+
+ has_varargs = 0;
+ for (arg = expr->data.funccall.functype->args; arg; arg = arg->next) {
+ if (arg == &elipsis) {
+ has_varargs = 1;
+ break;
+ }
+ }
+
+ if (expr->data.funccall.functype->flags & FUNC_FLAGS_80) {
+ if (CMach_PassResultInHiddenArg(resultType))
+ node = expr->data.funccall.args->next->node;
+ else
+ node = expr->data.funccall.args->node;
+ }
+
+ infos = analyze_arguments(
+ node,
+ expr->data.funccall.args,
+ expr->data.funccall.functype->args,
+ used_regs,
+ &has_floats,
+ has_varargs);
+
+ if (infos)
+ evaluate_nested_function_calls(infos);
+
+ if (funcref->hascall) {
+ GEN_NODE_TO_GPR(funcref, &opnd, TYPE(&void_ptr), 0);
+ } else if (node && node->hascall) {
+ GEN_NODE_TO_GPR(node, &opnd, TYPE(&void_ptr), 0);
+ }
+
+ for (info = infos; info; info = info->next) {
+ if (info->flags & AIF_PassOnStack)
+ pass_in_memory(info);
+ }
+ for (info = infos; info; info = info->next) {
+ if ((info->flags & AIF_PassMask) == (AIF_PassInGPR | AIF_PassOnStack))
+ pass_in_register_and_memory(info);
+ }
+ for (info = infos; info; info = info->next) {
+ int flag = info->flags & AIF_PassMask;
+ if (
+ flag == AIF_PassInGPR ||
+ flag == AIF_PassInFPR ||
+ flag == AIF_PassInVR
+ )
+ pass_in_register(info);
+ }
+
+ if (funcref->type == EOBJREF) {
+ TypeClass *tclass;
+ SInt32 vfOffset;
+ if (CParser_IsVirtualFunction(funcref->data.objref, &tclass, &vfOffset)) {
+ load_virtual_function(
+ tclass,
+ vfOffset,
+ CMach_PassResultInHiddenArg(resultType) ? Register4 : Register3,
+ &opnd
+ );
+ branch_subroutine_indirect_ctr(&opnd, used_regs);
+ } else if (node) {
+ if (!node->hascall) {
+ GEN_NODE_TO_REG(node, 12, 0, &opnd);
+ ENSURE_GPR(&opnd, TYPE(&void_ptr), 12);
+ }
+ branch_subroutine_indirect(funcref->data.objref, &opnd, used_regs);
+ } else {
+ branch_subroutine(funcref->data.objref, needs_TOC_reload(funcref->data.objref), used_regs);
+ }
+ } else {
+ if (!funcref->hascall)
+ GEN_NODE_TO_REG(funcref, 12, 0, &opnd);
+ ENSURE_GPR(&opnd, TYPE(&void_ptr), 12);
+ branch_subroutine_indirect_ctr(&opnd, used_regs);
+ }
+
+ if (IS_TYPE_FLOAT(resultType)) {
+ output->optype = OpndType_FPR;
+ output->reg = used_virtual_registers[RegClass_FPR]++;
+ emitpcode(PC_FMR, output->reg, 1);
+ } else if (IS_TYPE_VECTOR(resultType)) {
+ output->optype = OpndType_VR;
+ output->reg = used_virtual_registers[RegClass_VR]++;
+ emitpcode(PC_VMR, output->reg, 2);
+ } else if (TYPE_FITS_IN_REGISTER(resultType)) {
+ if (resultType->size > 4) {
+ output->optype = OpndType_GPRPair;
+ output->reg = used_virtual_registers[RegClass_GPR]++;
+ output->regHi = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, output->reg, low_reg);
+ emitpcode(PC_MR, output->regHi, high_reg);
+ } else {
+ output->optype = OpndType_GPR;
+ output->reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, output->reg, 3);
+ }
+ } else {
+ output->optype = OpndType_Absolute;
+ output->immediate = 0;
+ }
+}
+
+static void branch_subroutine_indirect_ctr(Operand *addrOpnd, UInt32 *used_regs) {
+ if (addrOpnd->reg != 12)
+ emitpcode(PC_MR, 12, addrOpnd->reg);
+
+ emitpcode(PC_MTCTR, 12);
+ used_regs[RegClass_GPR] |= 1 << 12;
+ branch_subroutine_ctr(used_regs);
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c
new file mode 100644
index 0000000..359c980
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/InstrSelection.c
@@ -0,0 +1,5348 @@
+#include "compiler/InstrSelection.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/FunctionCalls.h"
+#include "compiler/Intrinsics.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StructMoves.h"
+#include "compiler/TOC.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+PrecomputedOperand *precomputedoperands;
+void (*cgdispatch[MAXEXPR + 1])(ENode *, short, short, Operand *);
+
+// forward decls
+static int ispowerof2(SInt32 val);
+static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output);
+static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output);
+static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output);
+static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output);
+static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output);
+static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output);
+static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output);
+static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output);
+static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output);
+static ENodeType invert_relop(ENodeType nt);
+
+#define IS_INT_CONST(node) ( ENODE_IS((node), EINTCONST) && IS_TYPE_INT((node)->rtype) && (node)->rtype->size <= 4 )
+#define IS_INT_CONST_ZERO(node) ( IS_INT_CONST(node) && (node)->data.intval.lo == 0 )
+
+void init_cgdispatch(void) {
+ ENodeType t;
+
+ for (t = 0; t <= MAXEXPR; t++)
+ cgdispatch[t] = gen_UNEXPECTED;
+
+ cgdispatch[EPOSTINC] = gen_POSTINCDEC;
+ cgdispatch[EPOSTDEC] = gen_POSTINCDEC;
+ cgdispatch[EINDIRECT] = gen_INDIRECT;
+ cgdispatch[EMONMIN] = gen_MONMIN;
+ cgdispatch[EBINNOT] = gen_BINNOT;
+ cgdispatch[ELOGNOT] = gen_LOGICAL;
+ cgdispatch[EFORCELOAD] = gen_FORCELOAD;
+ cgdispatch[EMUL] = gen_MUL;
+ cgdispatch[EDIV] = gen_DIV;
+ cgdispatch[EMODULO] = gen_MODULO;
+ cgdispatch[EADD] = gen_ADD;
+ cgdispatch[ESUB] = gen_SUB;
+ cgdispatch[ESHL] = gen_SHL;
+ cgdispatch[ESHR] = gen_SHR;
+ cgdispatch[ELESS] = gen_COMPARE;
+ cgdispatch[EGREATER] = gen_COMPARE;
+ cgdispatch[ELESSEQU] = gen_COMPARE;
+ cgdispatch[EGREATEREQU] = gen_COMPARE;
+ cgdispatch[EEQU] = gen_COMPARE;
+ cgdispatch[ENOTEQU] = gen_COMPARE;
+ cgdispatch[EAND] = gen_AND;
+ cgdispatch[EXOR] = gen_XOR;
+ cgdispatch[EOR] = gen_OR;
+ cgdispatch[ELAND] = gen_LOGICAL;
+ cgdispatch[ELOR] = gen_LOGICAL;
+ cgdispatch[EASS] = gen_ASS;
+ cgdispatch[ECOMMA] = gen_COMMA;
+ cgdispatch[ETYPCON] = gen_TYPCON;
+ cgdispatch[EBITFIELD] = gen_BITFIELD;
+ cgdispatch[EINTCONST] = gen_INTCONST;
+ cgdispatch[EFLOATCONST] = gen_FLOATCONST;
+ cgdispatch[ESTRINGCONST] = gen_STRINGCONST;
+ cgdispatch[ECOND] = gen_COND;
+ cgdispatch[EFUNCCALL] = gen_FUNCCALL;
+ cgdispatch[EFUNCCALLP] = gen_FUNCCALL;
+ cgdispatch[EOBJREF] = gen_OBJREF;
+ cgdispatch[ENULLCHECK] = gen_NULLCHECK;
+ cgdispatch[EPRECOMP] = gen_PRECOMP;
+ cgdispatch[EDEFINE] = gen_DEFINE;
+ cgdispatch[EREUSE] = gen_REUSE;
+ cgdispatch[EVECTOR128CONST] = gen_VECTOR128CONST;
+ cgdispatch[ECONDASS] = gen_CONDASS;
+}
+
+void gen_DEFINE(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Operand *op;
+
+ if (!expr->data.diadic.right) {
+ op = lalloc(sizeof(Operand));
+ memclrw(op, sizeof(Operand));
+ expr->data.diadic.right = (ENode *) op;
+ GEN_NODE(expr->data.diadic.left, op);
+ }
+
+ op = (Operand *) expr->data.diadic.right;
+ *output = *op;
+}
+
+void gen_REUSE(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner = expr->data.monadic;
+ CError_ASSERT(250, ENODE_IS(inner, EDEFINE));
+ gen_DEFINE(inner, outputReg, outputRegHi, output);
+}
+
+void gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ TypeBitfield *tbitfield;
+ ENode *inner;
+ Type *type;
+ Operand a;
+ Operand b;
+ Operand c;
+ Float fval;
+ int objReg;
+ int constReg;
+ int finalReg;
+ SInt32 incval;
+
+ inner = expr->data.monadic->data.monadic;
+ type = expr->rtype;
+ tbitfield = NULL;
+
+ memclrw(&a, sizeof(Operand));
+ memclrw(&b, sizeof(Operand));
+ memclrw(&c, sizeof(Operand));
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_POSTINCDEC(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) {
+ output->optype = OpndType_FPR;
+ output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FMR, output->reg, objReg);
+ fval = one_point_zero;
+ load_floating_constant(constReg = ALLOC_FPR(), type, &fval);
+
+ if (ENODE_IS(expr, EPOSTINC)) {
+ emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, objReg, objReg, constReg);
+ } else {
+ emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, objReg, objReg, constReg);
+ }
+ } else {
+ GEN_NODE(inner, &a);
+ indirect(&a, inner);
+ b = a;
+ ENSURE_FPR(&b, type, 0);
+
+ output->optype = OpndType_FPR;
+ output->reg = ALLOC_FPR();
+ emitpcode(PC_FMR, output->reg, b.reg);
+
+ fval = one_point_zero;
+ load_floating_constant(constReg = ALLOC_FPR(), type, &fval);
+
+ finalReg = ALLOC_FPR();
+ if (ENODE_IS(expr, EPOSTINC))
+ emitpcode((type->size == 4) ? PC_FADDS : PC_FADD, finalReg, b.reg, constReg);
+ else
+ emitpcode((type->size == 4) ? PC_FSUBS : PC_FSUB, finalReg, b.reg, constReg);
+
+ store_fp(finalReg, &a, type);
+ }
+ } else {
+ if (IS_TYPE_POINTER(type)) {
+ if (ENODE_IS(expr, EPOSTINC))
+ incval = TPTR_TARGET(type)->size;
+ else
+ incval = -TPTR_TARGET(type)->size;
+ } else {
+ if (ENODE_IS(expr, EPOSTINC))
+ incval = 1;
+ else
+ incval = -1;
+ }
+
+ if (ENODE_IS(inner, EOBJREF) && (objReg = OBJECT_REG(inner->data.objref))) {
+ output->optype = OpndType_GPR;
+ output->reg = (outputReg && outputReg != objReg) ? outputReg : ALLOC_GPR();
+ emitpcode(PC_MR, output->reg, objReg);
+ add_register_immediate(objReg, objReg, incval);
+ } else {
+ if (ENODE_IS(inner, EBITFIELD)) {
+ tbitfield = TYPE_BITFIELD(TPTR_TARGET(inner));
+ inner = inner->data.monadic;
+ }
+ GEN_NODE(inner, &a);
+ indirect(&a, inner);
+ b = a;
+ ENSURE_GPR(&b, type, 0);
+
+ if (tbitfield) {
+ c = b;
+ extract_bitfield(&c, tbitfield, 0, &b);
+ }
+ output->optype = OpndType_GPR;
+
+ output->reg = ALLOC_GPR();
+ emitpcode(PC_MR, output->reg, b.reg);
+
+ finalReg = ALLOC_GPR();
+ add_register_immediate(finalReg, b.reg, incval);
+
+ if (tbitfield) {
+ insert_bitfield(finalReg, &c, tbitfield);
+ finalReg = c.reg;
+ }
+
+ store(finalReg, &a, type);
+ }
+ }
+}
+
+void gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *inner;
+ VarInfo *vi;
+ SInt32 postincvalue;
+ Operand op;
+
+ type = expr->rtype;
+ inner = expr->data.monadic;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_INDIRECT(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ memclrw(&op, sizeof(Operand));
+ if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) {
+ vi = Registers_GetVarInfo(inner->data.objref);
+ switch (vi->rclass) {
+ case RegClass_GPR:
+ output->optype = OpndType_GPR;
+ break;
+ case RegClass_FPR:
+ output->optype = OpndType_FPR;
+ break;
+ case RegClass_VR:
+ output->optype = OpndType_VR;
+ break;
+ case RegClass_CRFIELD:
+ output->optype = OpndType_CRField;
+ break;
+ default:
+ CError_FATAL(456);
+ }
+ output->reg = vi->reg;
+ output->object = NULL;
+ return;
+ }
+
+ if (ENODE_IS(inner, EBITFIELD)) {
+ GEN_NODE(inner->data.monadic, &op);
+ indirect(&op, expr);
+ ENSURE_GPR(&op, type, 0);
+ extract_bitfield(&op, TYPE_BITFIELD(inner->rtype), outputReg, output);
+ return;
+ }
+
+ if (ispostincrementopportunity(inner, &op, &postincvalue) && (TYPE_FITS_IN_REGISTER(type) || IS_TYPE_FLOAT(type) || IS_TYPE_VECTOR(type))) {
+ indirect(&op, expr);
+ *output = op;
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ ENSURE_GPR(output, type, outputReg);
+ } else if (IS_TYPE_FLOAT(type)) {
+ ENSURE_FPR(output, type, outputReg);
+ } else {
+ ENSURE_VR(output, type, outputReg);
+ }
+
+ add_register_immediate(op.reg, op.reg, postincvalue);
+ return;
+ }
+
+ GEN_NODE(inner, output);
+ indirect(output, expr);
+}
+
+void gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Type *type;
+ ENode *scan;
+
+ inner = expr->data.monadic;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_MONMIN(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FNMADDS : PC_FNMADD,
+ inner->data.diadic.left->data.diadic.left,
+ inner->data.diadic.left->data.diadic.right,
+ inner->data.diadic.right,
+ outputReg,
+ output);
+ } else if (ENODE_IS(inner, EADD) && ENODE_IS(inner->data.diadic.right, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FNMADDS : PC_FNMADD,
+ inner->data.diadic.right->data.diadic.left,
+ inner->data.diadic.right->data.diadic.right,
+ inner->data.diadic.left,
+ outputReg,
+ output);
+ } else if (ENODE_IS(inner, ESUB) && ENODE_IS(inner->data.diadic.left, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB,
+ inner->data.diadic.left->data.diadic.left,
+ inner->data.diadic.left->data.diadic.right,
+ inner->data.diadic.right,
+ outputReg,
+ output);
+ } else {
+ fp_unary_operator(PC_FNEG, inner, outputReg, output);
+ }
+ return;
+ }
+
+ scan = inner;
+ while (ENODE_IS(scan, ETYPCON) && IS_TYPE_INT_OR_ENUM(type) && !is_unsigned(type))
+ scan = scan->data.monadic;
+
+ switch (scan->type) {
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ if (TYPE_FITS_IN_REGISTER(scan->data.diadic.left->rtype) && TYPE_FITS_IN_REGISTER(scan->data.diadic.right->rtype)) {
+ gen_negated_condition_gpr(scan, output, outputReg);
+ return;
+ }
+ }
+ unary_operator(PC_NEG, inner, outputReg, output);
+}
+
+void gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Type *type;
+
+ inner = expr->data.monadic;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_BINNOT(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(inner, EAND))
+ binary_operator(PC_NAND, inner->data.diadic.left, inner->data.diadic.right, outputReg, output);
+ else if (ENODE_IS(inner, EOR))
+ binary_operator(PC_NOR, inner->data.diadic.left, inner->data.diadic.right, outputReg, output);
+ else if (ENODE_IS(inner, EXOR))
+ binary_operator(PC_EQV, inner->data.diadic.left, inner->data.diadic.right, outputReg, output);
+ else
+ unary_operator(PC_NOT, inner, outputReg, output);
+}
+
+void gen_FORCELOAD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+
+ inner = expr->data.monadic;
+ GEN_NODE(inner, output);
+
+ if (IS_TYPE_FLOAT(inner->rtype)) {
+ ENSURE_FPR(output, inner->rtype, outputReg);
+ } else if (IS_TYPE_VECTOR(inner->rtype)) {
+ ENSURE_VR(output, inner->rtype, outputReg);
+ } else if (TYPE_FITS_IN_REGISTER(inner->rtype)) {
+ if (TYPE_IS_8BYTES(inner->rtype))
+ coerce_to_register_pair(output, inner->rtype, outputReg, outputRegHi);
+ else
+ ENSURE_GPR(output, inner->rtype, outputReg);
+ } else if (!IS_TYPE_VOID(inner->rtype)) {
+ CError_FATAL(681);
+ }
+}
+
+void gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ Type *type;
+ int tmp;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_MUL(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ fp_binary_operator((type->size == 4) ? PC_FMULS : PC_FMUL, left, right, outputReg, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) {
+ shift_left_immediate(left, tmp, 0, outputReg, output);
+ } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) {
+ shift_left_immediate(left, tmp, 1, outputReg, output);
+ } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(left->data.intval.lo))) {
+ shift_left_immediate(right, tmp, 0, outputReg, output);
+ } else if (ENODE_IS(left, EINTCONST) && (tmp = ispowerof2(-left->data.intval.lo))) {
+ shift_left_immediate(right, tmp, 1, outputReg, output);
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT(right->data.intval.lo)) {
+ binary_immediate(PC_MULLI, left, right->data.intval.lo, outputReg, output);
+ } else if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo)) {
+ binary_immediate(PC_MULLI, right, left->data.intval.lo, outputReg, output);
+ } else {
+ binary_operator(PC_MULLW, left, right, outputReg, output);
+ }
+}
+
+struct ms {
+ SInt32 m;
+ int s;
+};
+static void create_signed_magic(SInt32 val, struct ms *output) {
+ // PowerPC CWG page 57-58
+ int p;
+ UInt32 ad, anc, delta, q1, r1, q2, r2, t;
+
+ ad = abs(val);
+ t = 0x80000000U + ((UInt32) val >> 31);
+ anc = t - 1 - t % ad;
+ p = 31;
+ q1 = 0x80000000U / anc;
+ r1 = 0x80000000U - q1 * anc;
+ q2 = 0x80000000U / ad;
+ r2 = 0x80000000U - q2 * ad;
+
+ do {
+ p = p + 1;
+ q1 = 2 * q1;
+ r1 = 2 * r1;
+ if (r1 >= anc) {
+ q1 = q1 + 1;
+ r1 = r1 - anc;
+ }
+ q2 = 2 * q2;
+ r2 = 2 * r2;
+ if (r2 >= ad) {
+ q2 = q2 + 1;
+ r2 = r2 - ad;
+ }
+ delta = ad - r2;
+ } while (q1 < delta || (q1 == delta && r1 == 0));
+
+ // after loop
+ output->m = q2 + 1;
+ if (val < 0)
+ output->m = -output->m;
+ output->s = p - 32;
+}
+
+struct mu {
+ UInt32 m;
+ int a;
+ int s;
+};
+static void create_unsigned_magic(UInt32 val, struct mu *output) {
+ // PowerPC CWG page 58-59
+ int p;
+ UInt32 nc, delta, q1, r1, q2, r2;
+
+ output->a = 0;
+ nc = - 1 - (-val) % val;
+ p = 31;
+ q1 = 0x80000000U / nc;
+ r1 = 0x80000000U - q1 * nc;
+ q2 = 0x7FFFFFFFU / val;
+ r2 = 0x7FFFFFFFU - q2 * val;
+ do {
+ p = p + 1;
+ if (r1 >= nc - r1) {
+ q1 = 2 * q1 + 1;
+ r1 = 2 * r1 - nc;
+ } else {
+ q1 = 2 * q1;
+ r1 = 2 * r1;
+ }
+ if (r2 + 1 >= val - r2) {
+ if (q2 >= 0x7FFFFFFFU)
+ output->a = 1;
+ q2 = 2 * q2 + 1;
+ r2 = 2 * r2 + 1 - val;
+ } else {
+ if (q2 >= 0x80000000U)
+ output->a = 1;
+ q2 = 2 * q2;
+ r2 = 2 * r2 + 1;
+ }
+ delta = val - 1 - r2;
+ } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0)));
+
+ output->m = q2 + 1;
+ output->s = p - 32;
+}
+
+void gen_DIV(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ Type *type;
+ int tmp;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ fp_binary_operator((type->size == 4) ? PC_FDIVS : PC_FDIV, left, right, outputReg, output);
+ return;
+ }
+
+ if (is_unsigned(type)) {
+ if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) {
+ shift_right_immediate(left, type, tmp, outputReg, output);
+ } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && right->data.intval.lo != 1) {
+ SInt32 value;
+ int tmpreg1;
+ int tmpreg2;
+ int tmpreg3;
+ int tmpreg4;
+ int tmpreg5;
+ int tmpreg6;
+ int finalReg;
+ struct mu u_magicoutput;
+ Operand op1;
+ value = right->data.intval.lo;
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ memclrw(&op1, sizeof(Operand));
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+
+ tmpreg3 = op1.reg;
+ create_unsigned_magic(value, &u_magicoutput);
+ load_immediate(tmpreg2, u_magicoutput.m);
+ emitpcode(PC_MULHWU, tmpreg1, tmpreg2, tmpreg3);
+ if (u_magicoutput.a == 0) {
+ if (u_magicoutput.s)
+ emitpcode(PC_RLWINM, finalReg, tmpreg1, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31);
+ else
+ emitpcode(PC_MR, finalReg, tmpreg1);
+ } else if (u_magicoutput.a == 1) {
+ tmpreg4 = ALLOC_GPR();
+ if (copts.optimizationlevel > 1) {
+ tmpreg5 = ALLOC_GPR();
+ tmpreg6 = ALLOC_GPR();
+ } else {
+ tmpreg5 = tmpreg4;
+ tmpreg6 = tmpreg4;
+ }
+
+ emitpcode(PC_SUBF, tmpreg4, tmpreg1, tmpreg3);
+ emitpcode(PC_RLWINM, tmpreg5, tmpreg4, 31, 1, 31);
+ emitpcode(PC_ADD, tmpreg6, tmpreg5, tmpreg1);
+ emitpcode(PC_RLWINM, finalReg, tmpreg6, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ } else {
+ binary_operator(PC_DIVWU, left, right, outputReg, output);
+ }
+ } else {
+ SInt32 value;
+ if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) {
+ signed_divide_by_power_of_2(left, tmp, 0, outputReg, output);
+ } else if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(-right->data.intval.lo))) {
+ signed_divide_by_power_of_2(left, tmp, 1, outputReg, output);
+ } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) {
+ int tmpreg2;
+ int tmpreg3;
+ int tmpreg1;
+ int tmpreg4;
+ int finalReg;
+ struct ms s_magicoutput;
+ Operand op2;
+ value = right->data.intval.lo;
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ memclrw(&op2, sizeof(Operand));
+ GEN_NODE(left, &op2);
+ ENSURE_GPR(&op2, left->rtype, 0);
+
+ tmpreg4 = op2.reg;
+ create_signed_magic(value, &s_magicoutput);
+ load_immediate(tmpreg2, s_magicoutput.m);
+ emitpcode(PC_MULHW, tmpreg1, tmpreg2, tmpreg4);
+ if (value > 0 && s_magicoutput.m < 0) {
+ int t = ALLOC_GPR();
+ emitpcode(PC_ADD, t, tmpreg1, tmpreg4);
+ tmpreg1 = t;
+ } else if (value < 0 && s_magicoutput.m > 0) {
+ int t = ALLOC_GPR();
+ emitpcode(PC_SUBF, t, tmpreg4, tmpreg1);
+ tmpreg1 = t;
+ }
+
+ if (s_magicoutput.s) {
+ int t = ALLOC_GPR();
+ emitpcode(PC_SRAWI, t, tmpreg1, s_magicoutput.s);
+ tmpreg1 = t;
+ }
+
+ emitpcode(PC_RLWINM, tmpreg3, tmpreg1, 1, 31, 31);
+ emitpcode(PC_ADD, finalReg, tmpreg1, tmpreg3);
+
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ } else {
+ binary_operator(PC_DIVW, left, right, outputReg, output);
+ }
+ }
+}
+
+void gen_MODULO(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ int tmp;
+ struct mu u_magicoutput;
+ struct ms s_magicoutput;
+ Operand op1;
+ Operand op2;
+ SInt32 value;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ I8_gen_DIV_MOD(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST) && (tmp = ispowerof2(right->data.intval.lo))) {
+ if (is_unsigned(expr->rtype))
+ shift_and_mask(left, 0, 32 - tmp, 31, outputReg, output);
+ else
+ signed_mod_by_power_of_2(left, tmp, 0, outputReg, output);
+ } else if (!copts.optimizesize && ENODE_IS(right, EINTCONST) && (value = right->data.intval.lo) != 1u && value != -1) {
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+
+ if (is_unsigned(expr->rtype)) {
+ int tmpreg1;
+ int tmpreg2;
+ int tmpreg3;
+ int tmpreg4;
+ int tmpreg5;
+ int tmpreg6;
+ int tmpreg7;
+ int tmpreg8;
+ int finalReg;
+
+ tmpreg1 = op1.reg;
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ create_unsigned_magic(right->data.intval.lo, &u_magicoutput);
+ load_immediate(tmpreg3, u_magicoutput.m);
+ emitpcode(PC_MULHWU, tmpreg2, tmpreg3, tmpreg1);
+
+ if (u_magicoutput.a == 0 && u_magicoutput.s != 0)
+ emitpcode(PC_RLWINM, tmpreg2, tmpreg2, (32 - u_magicoutput.s) & 31, u_magicoutput.s, 31);
+
+ if (u_magicoutput.a == 1) {
+ tmpreg5 = ALLOC_GPR();
+ if (copts.optimizationlevel > 1) {
+ tmpreg6 = ALLOC_GPR();
+ tmpreg7 = ALLOC_GPR();
+ tmpreg8 = ALLOC_GPR();
+ } else {
+ tmpreg6 = tmpreg5;
+ tmpreg7 = tmpreg5;
+ tmpreg8 = tmpreg5;
+ }
+ emitpcode(PC_SUBF, tmpreg5, tmpreg2, tmpreg1);
+ emitpcode(PC_RLWINM, tmpreg6, tmpreg5, 31, 1, 31);
+ emitpcode(PC_ADD, tmpreg7, tmpreg6, tmpreg2);
+ emitpcode(PC_RLWINM, tmpreg8, tmpreg7, (32 - (u_magicoutput.s - 1)) & 31, u_magicoutput.s - 1, 31);
+ tmpreg2 = tmpreg8;
+ }
+
+ if (value > 0 && value < 0x7FFF) {
+ emitpcode(PC_MULLI, tmpreg4, tmpreg2, value);
+ } else {
+ GEN_NODE(right, &op2);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ emitpcode(PC_MULLW, tmpreg4, tmpreg2, op2.reg);
+ }
+
+ emitpcode(PC_SUBF, finalReg, tmpreg4, tmpreg1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ } else {
+ int tmpreg1;
+ int tmpreg2;
+ int tmpreg3;
+ int tmpreg4;
+ int tmpreg5;
+ int tmpreg6;
+ int finalReg;
+
+ tmpreg1 = op1.reg;
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ tmpreg5 = ALLOC_GPR();
+ tmpreg6 = ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ create_signed_magic(right->data.intval.lo, &s_magicoutput);
+ load_immediate(tmpreg3, s_magicoutput.m);
+ emitpcode(PC_MULHW, tmpreg2, tmpreg3, tmpreg1);
+
+ if (value > 0 && s_magicoutput.m < 0) {
+ int tmp = ALLOC_GPR();
+ emitpcode(PC_ADD, tmp, tmpreg2, tmpreg1);
+ tmpreg2 = tmp;
+ } else if (value < 0 && s_magicoutput.m > 0) {
+ int tmp = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmp, tmpreg1, tmpreg2);
+ tmpreg2 = tmp;
+ }
+
+ if (s_magicoutput.s != 0) {
+ int tmp = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmp, tmpreg2, s_magicoutput.s);
+ tmpreg2 = tmp;
+ }
+
+ emitpcode(PC_RLWINM, tmpreg4, tmpreg2, 1, 31, 31);
+ emitpcode(PC_ADD, tmpreg5, tmpreg2, tmpreg4);
+
+ if (value < 0x7FFF && value > -0x4000) {
+ emitpcode(PC_MULLI, tmpreg6, tmpreg5, value);
+ } else {
+ GEN_NODE(right, &op2);
+ ENSURE_GPR(&op2, right->rtype, 0);
+
+ emitpcode(PC_MULLW, tmpreg6, tmpreg5, op2.reg);
+ }
+
+ emitpcode(PC_SUBF, finalReg, tmpreg6, tmpreg1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ }
+ } else {
+ int tmpreg1;
+ int tmpreg2;
+ int finalReg;
+
+ if (right->hascall) {
+ GEN_NODE(right, &op2);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ GEN_NODE(right, &op2);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ emitpcode(is_unsigned(expr->rtype) ? PC_DIVWU : PC_DIVW, tmpreg1, op1.reg, op2.reg);
+ emitpcode(PC_MULLW, tmpreg2, tmpreg1, op2.reg);
+ emitpcode(PC_SUBF, finalReg, tmpreg2, op1.reg);
+
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ }
+}
+
+void gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ Type *type;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_ADD(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ if (ENODE_IS(left, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FMADDS : PC_FMADD,
+ left->data.diadic.left,
+ left->data.diadic.right,
+ right,
+ outputReg, output);
+ } else if (ENODE_IS(right, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FMADDS : PC_FMADD,
+ right->data.diadic.left,
+ right->data.diadic.right,
+ left,
+ outputReg, output);
+ } else {
+ fp_binary_operator(
+ (type->size == 4) ? PC_FADDS : PC_FADD,
+ left, right,
+ outputReg, output);
+ }
+ return;
+ }
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (opright.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ GEN_NODE(left, &opleft);
+ if (opleft.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ if (opleft.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&opleft, left->rtype, 0);
+
+ GEN_NODE(right, &opright);
+ if (opright.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&opright, right->rtype, 0);
+ }
+
+ if (IS_TYPE_POINTER(expr->rtype)) {
+ if (TYPE_IS_8BYTES(expr->data.diadic.left->rtype)) {
+ opleft.optype = OpndType_GPR;
+ opleft.regHi = 0;
+ }
+ if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype)) {
+ opright.optype = OpndType_GPR;
+ opright.regHi = 0;
+ }
+ }
+
+ combine(&opleft, &opright, outputReg, output);
+}
+
+void gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ Type *type;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_SUB(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ if (ENODE_IS(left, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FMSUBS : PC_FMSUB,
+ left->data.diadic.left,
+ left->data.diadic.right,
+ right,
+ outputReg, output);
+ } else if (ENODE_IS(right, EMUL) && copts.fp_contract) {
+ fp_multiply_add(
+ (type->size == 4) ? PC_FNMSUBS : PC_FNMSUB,
+ right->data.diadic.left,
+ right->data.diadic.right,
+ left,
+ outputReg, output);
+ } else {
+ fp_binary_operator(
+ (type->size == 4) ? PC_FSUBS : PC_FSUB,
+ left, right,
+ outputReg, output);
+ }
+ return;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT(left->data.intval.lo))
+ binary_immediate(PC_SUBFIC, right, left->data.intval.lo, outputReg, output);
+ else
+ binary_operator(PC_SUBF, right, left, outputReg, output);
+}
+
+void gen_SHL(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST))
+ shift_left_immediate(left, right->data.intval.lo, 0, outputReg, output);
+ else
+ binary_operator(PC_SLW, left, right, outputReg, output);
+}
+
+void gen_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_SHL_SHR(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST))
+ shift_right_immediate(left, type, right->data.intval.lo, outputReg, output);
+ else
+ binary_operator(is_unsigned(type) ? PC_SRW : PC_SRAW, left, right, outputReg, output);
+}
+
+void gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+ short first;
+ short last;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_AND(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST) && ismaskconstant(right->data.intval.lo, &first, &last)) {
+ if (ENODE_IS(left, ESHL) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)(left->data.diadic.right->data.intval.lo + last) < 32) {
+ shift_and_mask(
+ left->data.diadic.left,
+ left->data.diadic.right->data.intval.lo,
+ first, last,
+ outputReg, output);
+ } else if (ENODE_IS(left, ESHR) && ENODE_IS(left->data.diadic.right, EINTCONST) && (int)left->data.diadic.right->data.intval.lo <= first && last >= first) {
+ if (left->data.diadic.right->data.intval.lo == 0)
+ shift_and_mask(left->data.diadic.left, 0, first, last, outputReg, output);
+ else
+ shift_and_mask(left->data.diadic.left, 32 - left->data.diadic.right->data.intval.lo, first, last, outputReg, output);
+ } else {
+ shift_and_mask(left, 0, first, last, outputReg, output);
+ }
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST) && FITS_IN_USHORT(right->data.intval.lo)) {
+ binary_immediate(PC_ANDI, left, right->data.intval.lo, outputReg, output);
+ return;
+ }
+ if (ENODE_IS(right, EINTCONST) && FITS_IN_HI_SHORT(right->data.intval.lo)) {
+ binary_immediate(PC_ANDIS, left, right->data.intval.lo >> 16, outputReg, output);
+ return;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && ismaskconstant(left->data.intval.lo, &first, &last)) {
+ if (ENODE_IS(right, ESHL) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)(right->data.diadic.right->data.intval.lo + last) < 32) {
+ shift_and_mask(
+ right->data.diadic.left,
+ right->data.diadic.right->data.intval.lo,
+ first, last,
+ outputReg, output);
+ } else if (ENODE_IS(right, ESHR) && ENODE_IS(right->data.diadic.right, EINTCONST) && (int)right->data.diadic.right->data.intval.lo <= first) {
+ if (right->data.diadic.right->data.intval.lo == 0)
+ shift_and_mask(right->data.diadic.left, 0, first, last, outputReg, output);
+ else
+ shift_and_mask(right->data.diadic.left, 32 - right->data.diadic.right->data.intval.lo, first, last, outputReg, output);
+ } else {
+ shift_and_mask(right, 0, first, last, outputReg, output);
+ }
+ return;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_USHORT(left->data.intval.lo)) {
+ binary_immediate(PC_ANDI, right, left->data.intval.lo, outputReg, output);
+ return;
+ }
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_HI_SHORT(left->data.intval.lo)) {
+ binary_immediate(PC_ANDIS, right, left->data.intval.lo >> 16, outputReg, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EBINNOT))
+ binary_operator(PC_ANDC, left, right->data.monadic, outputReg, output);
+ else if (ENODE_IS(left, EBINNOT))
+ binary_operator(PC_ANDC, right, left->data.monadic, outputReg, output);
+ else
+ binary_operator(PC_AND, left, right, outputReg, output);
+}
+
+void gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_XOR(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(left, EINTCONST))
+ or_xor_immediate(PC_XORI, right, left->data.intval.lo, outputReg, output);
+ else if (ENODE_IS(right, EINTCONST))
+ or_xor_immediate(PC_XORI, left, right->data.intval.lo, outputReg, output);
+ else if (ENODE_IS(right, EBINNOT))
+ binary_operator(PC_EQV, left, right->data.monadic, outputReg, output);
+ else if (ENODE_IS(left, EBINNOT))
+ binary_operator(PC_EQV, left->data.monadic, right, outputReg, output);
+ else
+ binary_operator(PC_XOR, left, right, outputReg, output);
+}
+
+void gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ type = expr->rtype;
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_OR(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(left, EINTCONST))
+ or_xor_immediate(PC_ORI, right, left->data.intval.lo, outputReg, output);
+ else if (ENODE_IS(right, EINTCONST))
+ or_xor_immediate(PC_ORI, left, right->data.intval.lo, outputReg, output);
+ else if (ENODE_IS(right, EBINNOT))
+ binary_operator(PC_ORC, left, right->data.monadic, outputReg, output);
+ else if (ENODE_IS(left, EBINNOT))
+ binary_operator(PC_ORC, right, left->data.monadic, outputReg, output);
+ else
+ binary_operator(PC_OR, left, right, outputReg, output);
+}
+
+void gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ Operand op2;
+ VarInfo *vi;
+ SInt32 incval;
+ short align;
+ short align2;
+
+ type = expr->rtype;
+ if (ENODE_IS(expr, ECONDASS)) {
+ left = expr->data.cond.expr1;
+ if (ENODE_IS(left, EINDIRECT)) {
+ left = left->data.monadic;
+ } else {
+ CError_FATAL(1759);
+ }
+ right = expr->data.cond.expr2;
+ } else {
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ }
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ if (TYPE_IS_8BYTES(type)) {
+ I8_gen_ASS(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) {
+ vi = Registers_GetVarInfo(left->data.objref);
+ GEN_NODE_TO_REG(right, vi->reg, 0, &opright);
+ switch (vi->rclass) {
+ case RegClass_GPR:
+ ENSURE_GPR(&opright, type, vi->reg);
+ output->optype = OpndType_GPR;
+ break;
+ case RegClass_FPR:
+ ENSURE_FPR(&opright, type, vi->reg);
+ output->optype = OpndType_FPR;
+ break;
+ case RegClass_VR:
+ ENSURE_VR(&opright, type, vi->reg);
+ output->optype = OpndType_VR;
+ break;
+ default:
+ CError_FATAL(1810);
+ }
+ if (opright.reg != vi->reg) {
+ PCodeArg a, b;
+ a.kind = PCOp_REGISTER;
+ a.arg = vi->rclass;
+ a.data.reg.reg = vi->reg;
+ a.data.reg.effect = EffectWrite;
+ b.kind = PCOp_REGISTER;
+ b.arg = vi->rclass;
+ b.data.reg.reg = opright.reg;
+ b.data.reg.effect = EffectRead;
+ appendpcode(pclastblock, makecopyinstruction(&b, &a));
+ }
+ output->reg = vi->reg;
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(type)) {
+ GEN_NODE_TO_FPR(right, &opright, right->rtype, 0);
+ if (ispostincrementopportunity(left, &opleft, &incval)) {
+ indirect(&opleft, expr);
+ store_fp(opright.reg, &opleft, type);
+ add_register_immediate(opleft.reg, opleft.reg, incval);
+ } else {
+ GEN_NODE(left, &opleft);
+ indirect(&opleft, expr);
+ store_fp(opright.reg, &opleft, type);
+ }
+ output->optype = OpndType_FPR;
+ output->reg = opright.reg;
+ return;
+ }
+
+ if (IS_TYPE_VECTOR(type)) {
+ GEN_NODE(right, &opright);
+ if (opright.optype == OpndType_Absolute)
+ ENSURE_VR(&opright, type, 0);
+ else
+ ENSURE_VR(&opright, right->rtype, 0);
+
+ if (ispostincrementopportunity(left, &opleft, &incval)) {
+ indirect(&opleft, expr);
+ store_v(opright.reg, &opleft, type);
+ add_register_immediate(opleft.reg, opleft.reg, incval);
+ } else {
+ GEN_NODE(left, &opleft);
+ indirect(&opleft, expr);
+ store_v(opright.reg, &opleft, type);
+ }
+ output->optype = OpndType_VR;
+ output->reg = opright.reg;
+ return;
+ }
+
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ GEN_NODE_TO_GPR(right, &opright, right->rtype, 0);
+
+ if (ENODE_IS(left, EBITFIELD)) {
+ GEN_NODE(left->data.monadic, &opleft);
+ indirect(&opleft, expr);
+
+ op2 = opleft;
+ ENSURE_GPR(&op2, type, 0);
+ insert_bitfield(opright.reg, &op2, TYPE_BITFIELD(left->rtype));
+ store(op2.reg, &opleft, type);
+
+ if (!expr->ignored)
+ extract_bitfield(&op2, TYPE_BITFIELD(left->rtype), opright.reg, &opleft);
+ } else if (ispostincrementopportunity(left, &opleft, &incval)) {
+ indirect(&opleft, expr);
+ store(opright.reg, &opleft, type);
+ add_register_immediate(opleft.reg, opleft.reg, incval);
+ } else {
+ GEN_NODE(left, &opleft);
+ indirect(&opleft, expr);
+ store(opright.reg, &opleft, type);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = opright.reg;
+ return;
+ }
+
+ GEN_NODE(right, &opright);
+ GEN_NODE(left, output);
+
+ indirect(output, expr);
+ if (output->object) {
+ if (output->object->datatype == DLOCAL && (output->object->u.var.info->flags & VarInfoFlag1))
+ align = CMach_ArgumentAlignment(type);
+ else
+ align = CMach_AllocationAlignment(type, output->object->qual);
+ } else {
+ align = CMach_AllocationAlignment(type, 0);
+ }
+ if (opright.object) {
+ if (opright.object->datatype == DLOCAL && (opright.object->u.var.info->flags & VarInfoFlag1))
+ align2 = CMach_ArgumentAlignment(type);
+ else
+ align2 = CMach_AllocationAlignment(type, opright.object->qual);
+ } else {
+ align2 = CMach_AllocationAlignment(type, 0);
+ }
+
+ if (align2 < align)
+ align = align2;
+
+ move_block(output, &opright, type->size, align);
+}
+
+ENode *evaluate_and_skip_comma(ENode *expr) {
+ Operand op;
+ ENode *inner;
+
+ memclrw(&op, sizeof(Operand));
+ while (ENODE_IS(expr, ECOMMA)) {
+ inner = expr->data.diadic.left;
+ GEN_NODE(inner, &op);
+ if (ENODE_IS(inner, EINDIRECT) && (op.flags & OpndFlags_Volatile)) {
+ if (TYPE_FITS_IN_REGISTER_2(inner->rtype)) {
+ ENSURE_GPR(&op, inner->rtype, 0);
+ } else if (IS_TYPE_FLOAT(inner->rtype)) {
+ ENSURE_FPR(&op, inner->rtype, 0);
+ }
+ }
+ expr = expr->data.diadic.right;
+ }
+ return expr;
+}
+
+void gen_COMMA(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ GEN_NODE(left, output);
+
+ if (ENODE_IS(left, EINDIRECT) && (output->flags & OpndFlags_Volatile)) {
+ if (TYPE_FITS_IN_REGISTER_2(left->rtype)) {
+ ENSURE_GPR(output, left->rtype, 0);
+ } else if (IS_TYPE_FLOAT(left->rtype)) {
+ ENSURE_FPR(output, left->rtype, 0);
+ }
+ }
+
+ GEN_NODE_TO_REG(right, outputReg, 0, output);
+}
+
+void gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Type *srctype;
+ Type *dsttype;
+
+ inner = expr->data.monadic;
+ srctype = inner->rtype;
+ dsttype = expr->rtype;
+
+ if (TYPE_IS_8BYTES(srctype) || TYPE_IS_8BYTES(dsttype)) {
+ I8_gen_TYPCON(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ if (IS_TYPE_VOID(dsttype)) {
+ GEN_NODE(inner, output);
+ if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile)) {
+ if (TYPE_FITS_IN_REGISTER_2(srctype)) {
+ ENSURE_GPR(output, srctype, 0);
+ } else if (IS_TYPE_FLOAT(srctype)) {
+ ENSURE_FPR(output, srctype, 0);
+ }
+ }
+ } else if (IS_TYPE_INT_OR_ENUM(srctype)) {
+ if (IS_TYPE_FLOAT(dsttype)) {
+ GEN_NODE(inner, output);
+ if (srctype->size < 4)
+ extend32(output, srctype, 0);
+ ENSURE_GPR(output, srctype, 0);
+
+ if (is_unsigned(srctype))
+ convert_unsigned_to_floating(output, dsttype->size == 4, outputReg);
+ else
+ convert_integer_to_floating(output, dsttype->size == 4, outputReg);
+ } else if (IS_TYPE_VECTOR(dsttype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ ENSURE_VR(output, dsttype, outputReg);
+ } else if (
+ srctype->size < dsttype->size &&
+ !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) &&
+ !ENODE_IS_ASSIGN_TO(inner, EBITFIELD) &&
+ !(ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD))
+ ) {
+ GEN_NODE(inner, output);
+ extend32(output, srctype, outputReg);
+ } else if (dsttype->size < srctype->size || dsttype->size < 4) {
+ GEN_NODE(inner, output);
+ ENSURE_GPR(output, srctype, 0);
+ extend32(output, dsttype, outputReg);
+ } else {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ }
+ } else if (IS_TYPE_POINTER(srctype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ if (dsttype->size < srctype->size)
+ ENSURE_GPR(output, srctype, outputReg);
+ } else if (IS_TYPE_FLOAT(srctype)) {
+ if (IS_TYPE_FLOAT(dsttype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ ENSURE_FPR(output, srctype, outputReg);
+
+ if (dsttype->size == 4 && srctype->size != 4) {
+ int tmp = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FRSP, tmp, output->reg);
+ output->optype = OpndType_FPR;
+ output->reg = tmp;
+ }
+ } else if (is_unsigned(dsttype) && dsttype->size == 4) {
+ GEN_NODE_TO_REG(inner, 1, 0, output);
+ ENSURE_FPR(output, srctype, 1);
+ convert_floating_to_unsigned(output, outputReg);
+ } else {
+ GEN_NODE_TO_REG(inner, 0, 0, output);
+ ENSURE_FPR(output, srctype, 0);
+ convert_floating_to_integer(output, outputReg);
+ }
+ } else if (IS_TYPE_VECTOR(srctype) && IS_TYPE_VECTOR(dsttype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ ENSURE_VR(output, srctype, outputReg);
+ } else if (srctype->size == dsttype->size) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ } else {
+ CError_FATAL(2224);
+ }
+}
+
+void gen_BITFIELD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ CError_FATAL(2238);
+}
+
+void gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ I8_gen_INTCONST(expr, outputReg, outputRegHi, output);
+ return;
+ }
+
+ output->optype = OpndType_Absolute;
+ output->immediate = CInt64_GetULong(&expr->data.intval);
+}
+
+void gen_FLOATCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ CError_FATAL(2294);
+}
+
+void gen_STRINGCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ CError_FATAL(2308);
+}
+
+static Boolean COND_is_ABS_MatchNodes(ENode *cond, ENode *expr1, ENode *expr2) {
+ if (cond->type != expr1->type || cond->type != expr2->type)
+ return 0;
+
+ if (!(TYPE_FITS_IN_REGISTER(cond->rtype) && TYPE_FITS_IN_REGISTER(expr1->rtype) && TYPE_FITS_IN_REGISTER(expr2->rtype)))
+ return 0;
+
+ if (cond->rtype->size != expr1->rtype->size || cond->rtype->size != expr2->rtype->size)
+ return 0;
+
+ switch (cond->type) {
+ case EOBJREF:
+ if (cond->data.objref != expr1->data.objref || cond->data.objref != expr2->data.objref)
+ return 0;
+ return 1;
+ case EINDIRECT:
+ case ETYPCON:
+ return COND_is_ABS_MatchNodes(cond->data.monadic, expr1->data.monadic, expr2->data.monadic);
+ default:
+ return 0;
+ }
+}
+
+static ENode *COND_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) {
+ ENode *tmp;
+
+ int parity = 0;
+ while (ENODE_IS(cond, ELOGNOT)) {
+ parity = (parity + 1) & 1;
+ cond = cond->data.monadic;
+ }
+
+ if (parity) {
+ tmp = expr1;
+ expr1 = expr2;
+ expr2 = tmp;
+ }
+
+ switch (cond->type) {
+ case ELESS:
+ case ELESSEQU:
+ tmp = expr1;
+ expr1 = expr2;
+ expr2 = tmp;
+ break;
+ case EGREATER:
+ case EGREATEREQU:
+ break;
+ default:
+ return NULL;
+ }
+
+ if (IS_INT_CONST_ZERO(cond->data.diadic.right)) {
+ cond = cond->data.diadic.left;
+ } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) {
+ cond = cond->data.diadic.left;
+ tmp = expr1;
+ expr1 = expr2;
+ expr2 = tmp;
+ } else {
+ return NULL;
+ }
+
+ if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) {
+ if (COND_is_ABS_MatchNodes(cond, expr1->data.diadic.right, expr2->data.diadic.right))
+ return expr1;
+ else
+ return NULL;
+ }
+
+ if (!ENODE_IS(expr2, EMONMIN))
+ return NULL;
+
+ expr2 = expr2->data.monadic;
+ if (COND_is_ABS_MatchNodes(cond, expr1, expr2))
+ return expr1;
+
+ return NULL;
+}
+
+static int COND_has_const(ENode *expr1, ENode *expr2) {
+ SInt32 diff;
+ int result = 0;
+
+ if (IS_INT_CONST(expr1))
+ result += 1;
+ if (IS_INT_CONST(expr2))
+ result += 2;
+
+ if (result & 1) {
+ if (IS_INT_CONST_ZERO(expr1))
+ return 5;
+ }
+ if (result & 2) {
+ if (IS_INT_CONST_ZERO(expr2))
+ return 6;
+ }
+
+ if (result == 3) {
+ diff = expr1->data.intval.lo - expr2->data.intval.lo;
+ if (diff == 1 || diff == -1)
+ return 4;
+ }
+
+ return result;
+}
+
+static Boolean COND_is_COMPARE(ENode *cond, ENode *expr1, ENode *expr2, short outputReg, Operand *output) {
+ SInt32 left;
+ SInt32 right;
+ int parity;
+ int negate;
+ ENodeType nt;
+
+ while (ENODE_IS(expr1, ETYPCON) && TYPE_FITS_IN_REGISTER(expr1->rtype))
+ expr1 = expr1->data.monadic;
+ while (ENODE_IS(expr2, ETYPCON) && TYPE_FITS_IN_REGISTER(expr2->rtype))
+ expr2 = expr2->data.monadic;
+
+ if (!(ENODE_IS(expr1, EINTCONST) && TYPE_FITS_IN_REGISTER(expr1->rtype) && CInt64_IsInRange(expr1->data.intval, 4)))
+ return 0;
+ if (!(ENODE_IS(expr2, EINTCONST) && TYPE_FITS_IN_REGISTER(expr2->rtype) && CInt64_IsInRange(expr2->data.intval, 4)))
+ return 0;
+
+ left = CInt64_GetULong(&expr1->data.intval);
+ right = CInt64_GetULong(&expr2->data.intval);
+ parity = 0;
+ negate = 0;
+ switch (left) {
+ case 1:
+ if (right != 0)
+ return 0;
+ break;
+ case 0:
+ parity = 1;
+ if (right == -1)
+ negate = 1;
+ else if (right != 1)
+ return 0;
+ break;
+ case -1:
+ if (right != 0)
+ return 0;
+ negate = 1;
+ break;
+ default:
+ return 0;
+ }
+
+ while (ENODE_IS(cond, ELOGNOT)) {
+ parity = (parity + 1) & 1;
+ cond = cond->data.monadic;
+ }
+
+ if (parity) {
+ nt = invert_relop(cond->type);
+ if (nt == cond->type)
+ return 0;
+ cond->type = nt;
+ }
+
+ if (negate)
+ gen_negated_condition_gpr(cond, output, outputReg);
+ else
+ gen_condition_gpr(cond, output, outputReg);
+
+ return 1;
+}
+
+void gen_COND(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *cond;
+ ENode *expr1;
+ ENode *expr2;
+ Type *type;
+ PCodeLabel *label1;
+ PCodeLabel *label2;
+ PCodeLabel *label3;
+ Operand op1;
+ Operand op2;
+ int has_const;
+ int reg1;
+ int reg2;
+ int reg3;
+ short align;
+ short max_align;
+
+ expr1 = expr->data.cond.expr1;
+ expr2 = expr->data.cond.expr2;
+ type = expr->rtype;
+
+ label1 = makepclabel();
+ label2 = makepclabel();
+ label3 = makepclabel();
+
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ cond = evaluate_and_skip_comma(expr->data.cond.cond);
+
+ if (TOC_use_fsel(expr)) {
+ ENode *left;
+ ENode *right;
+ ENode *tmp;
+ ENodeType nt;
+ Boolean flag;
+ Operand op;
+ int fneg_reg;
+ int fneg_reg2;
+ int fneg_reg3;
+ int fsel_reg;
+ int final_reg;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ nt = cond->type;
+ flag = 0;
+ memclrw(&op, sizeof(Operand));
+
+ switch (nt) {
+ case EGREATEREQU:
+ case EEQU:
+ break;
+ case EGREATER:
+ tmp = left;
+ left = right;
+ right = tmp;
+ case ELESS:
+ case ENOTEQU:
+ tmp = expr1;
+ expr1 = expr2;
+ expr2 = tmp;
+ break;
+ case ELESSEQU:
+ tmp = left;
+ left = right;
+ right = tmp;
+ break;
+ default:
+ CError_FATAL(2780);
+ }
+
+ if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) {
+ GEN_NODE(right, &op);
+ ENSURE_FPR(&op, right->rtype, 0);
+ flag = 1;
+ } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) {
+ GEN_NODE(left, &op);
+ ENSURE_FPR(&op, left->rtype, 0);
+ } else {
+ fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op);
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ case ENOTEQU:
+ if (flag) {
+ GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0);
+
+ fneg_reg = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg, op.reg);
+ fsel_reg = ALLOC_FPR();
+ emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg);
+ final_reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FSEL, final_reg, fneg_reg, fsel_reg, op2.reg);
+ } else {
+ GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0);
+
+ fneg_reg2 = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg2, op.reg);
+ fsel_reg = ALLOC_FPR();
+ emitpcode(PC_FSEL, fsel_reg, op.reg, op1.reg, op2.reg);
+ final_reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FSEL, final_reg, fneg_reg2, fsel_reg, op2.reg);
+ }
+ break;
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ GEN_NODE_TO_FPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0);
+
+ fneg_reg3 = op.reg;
+ if (flag) {
+ fneg_reg3 = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg3, op.reg);
+ }
+
+ final_reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FSEL, final_reg, fneg_reg3, op1.reg, op2.reg);
+ break;
+ default:
+ CError_FATAL(2862);
+ }
+
+ output->optype = OpndType_FPR;
+ output->reg = final_reg;
+ return;
+ }
+
+ if (TOC_use_isel(expr, 1)) {
+ Operand isel_op1;
+ Operand isel_op2;
+ ENode *x;
+ ENode *y;
+ ENode *abs_expr;
+
+ memclrw(&isel_op1, sizeof(Operand));
+ memclrw(&isel_op2, sizeof(Operand));
+
+ if (COND_is_COMPARE(cond, expr1, expr2, outputReg, output))
+ return;
+
+ if ((abs_expr = COND_is_ABS(cond, expr1, expr2))) {
+ if (ENODE_IS(expr1, EADD) && ENODE_IS(expr2, ESUB)) {
+ x = expr1->data.diadic.left;
+ y = expr2->data.diadic.right;
+ if (y->hascall) {
+ GEN_NODE(y, &op2);
+ ENSURE_GPR(&op2, y->rtype, 0);
+
+ GEN_NODE(x, &op1);
+ if (op1.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&op1, x->rtype, 0);
+ } else {
+ GEN_NODE(x, &op1);
+ if (op1.optype >= OpndType_IndirectGPR_ImmOffset)
+ ENSURE_GPR(&op1, x->rtype, 0);
+
+ GEN_NODE(y, &op2);
+ ENSURE_GPR(&op2, y->rtype, 0);
+ }
+
+ reg1 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, reg1, op2.reg, 31);
+ reg2 = ALLOC_GPR();
+ emitpcode(PC_XOR, reg2, reg1, op2.reg);
+ reg3 = ALLOC_GPR();
+ emitpcode(PC_SUBF, reg3, reg1, reg2);
+ op2.optype = OpndType_GPR;
+ op2.reg = reg3;
+ combine(&op1, &op2, outputReg, output);
+ } else {
+ GEN_NODE(abs_expr, output);
+ ENSURE_GPR(output, abs_expr->rtype, 0);
+
+ reg1 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, reg1, output->reg, 31);
+ reg2 = ALLOC_GPR();
+ emitpcode(PC_XOR, reg2, reg1, output->reg);
+ reg3 = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBF, reg3, reg1, reg2);
+ output->optype = OpndType_GPR;
+ output->reg = reg3;
+ }
+ return;
+ }
+
+ if ((has_const = COND_has_const(expr1, expr2))) {
+ switch (COND_has_const(expr1, expr2)) {
+ case 0:
+ case 2:
+ break;
+ case 3:
+ case 4:
+ if (has_const == 4) {
+ if (expr1->data.intval.lo < expr2->data.intval.lo)
+ gen_negated_condition_gpr(cond, &isel_op1, 0);
+ else
+ gen_condition_gpr(cond, &isel_op1, 0);
+
+ GEN_NODE(expr1, &op1);
+ GEN_NODE(expr2, &op2);
+ reg1 = ALLOC_GPR();
+ ENSURE_GPR(&op2, expr2->rtype, reg1);
+ emitpcode(PC_ADD, reg1, isel_op1.reg, op2.reg);
+ if (outputReg) {
+ emitpcode(PC_MR, reg2 = outputReg, reg1);
+ reg1 = reg2;
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg1;
+ return;
+ }
+ break;
+ case 5:
+ case 6:
+ gen_negated_condition_gpr(cond, &isel_op1, 0);
+ ENSURE_GPR(&isel_op1, TYPE(&stunsignedint), 0);
+ GEN_NODE(expr1, &op1);
+ GEN_NODE(expr2, &op2);
+
+ reg1 = outputReg ? outputReg : ALLOC_GPR();
+ if (op1.optype == OpndType_Absolute && op1.immediate == 0) {
+ ENSURE_GPR(&op2, expr2->rtype, 0);
+ emitpcode(PC_ANDC, reg1, op2.reg, isel_op1.reg);
+ } else if (op2.optype == OpndType_Absolute && op2.immediate == 0) {
+ ENSURE_GPR(&op1, expr1->rtype, 0);
+ emitpcode(PC_AND, reg1, op1.reg, isel_op1.reg);
+ } else {
+ CError_FATAL(3119);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg1;
+ return;
+ case 1:
+ reg2 = ALLOC_GPR();
+ reg1 = reg2;
+ logical_expression_nobranch(cond, 0, &isel_op2);
+
+ GEN_NODE_TO_REG(expr1, reg1, 0, &op1);
+ ENSURE_GPR(&op1, expr1->rtype, reg1);
+ if (op1.reg != reg1)
+ emitpcode(PC_MR, reg1, op1.reg);
+
+ branch_conditional(isel_op2.reg, isel_op2.regOffset, 1, label2);
+ branch_label(label1);
+
+ GEN_NODE_TO_REG(expr2, reg1, 0, &op2);
+ ENSURE_GPR(&op2, expr2->rtype, reg1);
+ if (op2.reg != reg1)
+ emitpcode(PC_MR, reg1, op2.reg);
+
+ branch_label(label2);
+
+ if (outputReg) {
+ emitpcode(PC_MR, reg2 = outputReg, reg1);
+ reg1 = reg2;
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg1;
+ return;
+
+ default:
+ CError_FATAL(3168);
+ }
+ }
+
+ reg1 = ALLOC_GPR();
+ logical_expression_nobranch(cond, 0, &isel_op2);
+
+ GEN_NODE_TO_REG(expr2, reg1, 0, &op2);
+ ENSURE_GPR(&op2, expr2->rtype, reg1);
+ if (op2.reg != reg1)
+ emitpcode(PC_MR, reg1, op2.reg);
+
+ branch_conditional(isel_op2.reg, isel_op2.regOffset, 0, label2);
+ branch_label(label1);
+
+ GEN_NODE_TO_REG(expr1, reg1, 0, &op1);
+ ENSURE_GPR(&op1, expr1->rtype, reg1);
+ if (op1.reg != reg1)
+ emitpcode(PC_MR, reg1, op1.reg);
+
+ branch_label(label2);
+
+ if (outputReg) {
+ emitpcode(PC_MR, reg2 = outputReg, reg1);
+ reg1 = reg2;
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg1;
+ return;
+ }
+
+ logical_expression(cond, label1, label2, label1);
+ branch_label(label1);
+
+ if (IS_TYPE_VOID(type) || expr->ignored) {
+ GEN_NODE(expr1, &op1);
+ branch_always(label3);
+ branch_label(label2);
+ GEN_NODE(expr2, &op2);
+ } else if (IS_TYPE_FLOAT(type)) {
+ if (expr1->hascall || expr2->hascall)
+ reg1 = ALLOC_FPR();
+ else
+ reg1 = outputReg ? outputReg : ALLOC_FPR();
+
+ GEN_NODE_TO_REG(expr1, reg1, 0, &op1);
+ ENSURE_FPR(&op1, expr1->rtype, reg1);
+ if (op1.reg != reg1)
+ emitpcode(PC_FMR, reg1, op1.reg);
+
+ branch_always(label3);
+ branch_label(label2);
+
+ GEN_NODE_TO_REG(expr2, reg1, 0, &op2);
+ ENSURE_FPR(&op2, expr2->rtype, reg1);
+ if (op2.reg != reg1)
+ emitpcode(PC_FMR, reg1, op2.reg);
+
+ output->optype = OpndType_FPR;
+ output->reg = reg1;
+ } else if (TYPE_IS_8BYTES(type)) {
+ if (expr1->hascall || expr2->hascall) {
+ reg1 = ALLOC_GPR();
+ reg3 = ALLOC_GPR();
+ reg2 = reg3;
+ } else {
+ reg1 = outputReg ? outputReg : ALLOC_GPR();
+ reg3 = outputRegHi ? outputRegHi : ALLOC_GPR();
+ reg2 = reg3;
+ }
+
+ GEN_NODE_TO_REG(expr1, reg1, reg2, &op1);
+ coerce_to_register_pair(&op1, expr1->rtype, reg1, reg2);
+
+ branch_always(label3);
+ branch_label(label2);
+
+ GEN_NODE_TO_REG(expr2, reg1, reg2, &op2);
+ coerce_to_register_pair(&op2, expr2->rtype, reg1, reg2);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg1;
+ output->regHi = reg2;
+ } else if (TYPE_FITS_IN_REGISTER(type)) {
+ if (expr1->hascall || expr2->hascall)
+ reg1 = ALLOC_GPR();
+ else
+ reg1 = outputReg ? outputReg : ALLOC_GPR();
+
+ GEN_NODE_TO_REG(expr1, reg1, 0, &op1);
+ ENSURE_GPR(&op1, expr1->rtype, reg1);
+ if (op1.reg != reg1)
+ emitpcode(PC_MR, reg1, op1.reg);
+
+ branch_always(label3);
+ branch_label(label2);
+
+ GEN_NODE_TO_REG(expr2, reg1, 0, &op2);
+ ENSURE_GPR(&op2, expr2->rtype, reg1);
+ if (op2.reg != reg1)
+ emitpcode(PC_MR, reg1, op2.reg);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg1;
+ } else if (IS_TYPE_VECTOR(type)) {
+ if (expr1->hascall || expr2->hascall)
+ reg1 = ALLOC_VR();
+ else
+ reg1 = outputReg ? outputReg : ALLOC_VR();
+
+ GEN_NODE_TO_REG(expr1, reg1, 0, &op1);
+ ENSURE_VR(&op1, expr1->rtype, reg1);
+ if (op1.reg != reg1)
+ emitpcode(PC_VMR, reg1, op1.reg);
+
+ branch_always(label3);
+ branch_label(label2);
+
+ GEN_NODE_TO_REG(expr2, reg1, 0, &op2);
+ ENSURE_VR(&op2, expr2->rtype, reg1);
+ if (op2.reg != reg1)
+ emitpcode(PC_VMR, reg1, op2.reg);
+
+ output->optype = OpndType_VR;
+ output->reg = reg1;
+ } else {
+ symbol_operand(output, maketemporary(type));
+ indirect(output, NULL);
+ coerce_to_addressable(output);
+
+ GEN_NODE(expr1, &op1);
+
+ if (op1.object) {
+ if (op1.object->datatype == DLOCAL && (op1.object->u.var.info->flags & VarInfoFlag1))
+ align = CMach_ArgumentAlignment(type);
+ else
+ align = CMach_AllocationAlignment(type, op1.object->qual);
+ } else {
+ align = CMach_AllocationAlignment(type, 0);
+ }
+
+ max_align = CMach_AllocationAlignment(type, 0);
+ if (align > max_align)
+ align = max_align;
+
+ move_block(output, &op1, type->size, align);
+
+ branch_always(label3);
+ branch_label(label2);
+
+ GEN_NODE(expr2, &op2);
+
+ if (op2.object) {
+ if (op2.object->datatype == DLOCAL && (op2.object->u.var.info->flags & VarInfoFlag1))
+ align = CMach_ArgumentAlignment(type);
+ else
+ align = CMach_AllocationAlignment(type, op2.object->qual);
+ } else {
+ align = CMach_AllocationAlignment(type, 0);
+ }
+
+ if (align > max_align)
+ align = max_align;
+
+ move_block(output, &op2, type->size, align);
+ }
+
+ branch_label(label3);
+}
+
+static Boolean CONDASS_is_ABS(ENode *cond, ENode *expr1, ENode *expr2) {
+ ENode *inner;
+
+ int parity = 0;
+ while (ENODE_IS(cond, ELOGNOT)) {
+ parity = (parity + 1) & 1;
+ cond = cond->data.monadic;
+ }
+
+ if (IS_INT_CONST_ZERO(cond->data.diadic.right)) {
+ inner = cond->data.diadic.left;
+ } else if (IS_INT_CONST_ZERO(cond->data.diadic.left)) {
+ inner = cond->data.diadic.left;
+ parity = (parity + 1) & 1;
+ } else {
+ return 0;
+ }
+
+ switch (cond->type) {
+ case EGREATER:
+ case EGREATEREQU:
+ if (!parity)
+ return 0;
+ break;
+ case ELESS:
+ case ELESSEQU:
+ if (parity)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!ENODE_IS(expr2, EMONMIN))
+ return 0;
+
+ expr2 = expr2->data.monadic;
+ if (ENODE_IS(inner, EASS)) {
+ inner = inner->data.diadic.left;
+ if (!ENODE_IS(expr2, EINDIRECT))
+ return 0;
+ expr2 = expr2->data.monadic;
+ if (!ENODE_IS(expr1, EINDIRECT))
+ return 0;
+ expr1 = expr1->data.monadic;
+ }
+
+ return COND_is_ABS_MatchNodes(inner, expr1, expr2);
+}
+
+static int CONDASS_is_OPASS_One(ENode *a, ENode *b, SInt32 *value, ENodeType *nodetype) {
+ Type *type;
+
+ type = a->rtype;
+ if (!ENODE_IS(a, EINDIRECT))
+ return 0;
+ a = a->data.monadic;
+ if (!ENODE_IS(a, EOBJREF))
+ return 0;
+
+ if (ENODE_IS(b, ETYPCON) && b->rtype == type)
+ b = b->data.monadic;
+
+ if (b->type != EOR && b->type != EADD && b->type != ESUB)
+ return 0;
+
+ *nodetype = b->type;
+ if (!IS_INT_CONST(b->data.diadic.right))
+ return 0;
+ *value = b->data.diadic.right->data.intval.lo;
+
+ if (*value != 1 && *value != -1)
+ return 0;
+
+ b = b->data.diadic.left;
+ if (ENODE_IS(b, ETYPCON) && TYPE_FITS_IN_REGISTER(b->rtype))
+ b = b->data.monadic;
+
+ if (!ENODE_IS(b, EINDIRECT))
+ return 0;
+ b = b->data.monadic;
+ if (!ENODE_IS(b, EOBJREF))
+ return 0;
+
+ if (a->data.objref == b->data.objref)
+ return 1;
+ return 0;
+}
+
+void gen_CONDASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *cond;
+ ENode *expr1;
+ ENode *expr2;
+ Type *type;
+ PCodeLabel *label1;
+ PCodeLabel *label2;
+ Operand op1;
+ Operand op2;
+ Operand op3;
+ int reg1;
+ int reg2;
+
+ expr1 = expr->data.cond.expr1;
+ expr2 = expr->data.cond.expr2;
+ type = expr->rtype;
+
+ label1 = makepclabel();
+ label2 = makepclabel();
+
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+ memclrw(&op3, sizeof(Operand));
+
+ cond = evaluate_and_skip_comma(expr->data.cond.cond);
+
+ if (TOC_use_fsel(expr)) {
+ ENode *left;
+ ENode *right;
+ ENode *tmp;
+ ENodeType nt;
+ Boolean flag;
+ Boolean flag2;
+ Operand op;
+ int tmpreg;
+ int fneg_reg;
+ int fsel_reg;
+ int final_reg;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ nt = cond->type;
+ flag = 0;
+ memclrw(&op, sizeof(Operand));
+
+ CError_ASSERT(3704, ENODE_IS(expr1, EINDIRECT));
+ CError_ASSERT(3705, ENODE_IS(expr1->data.monadic, EOBJREF));
+
+ tmpreg = OBJECT_REG(expr1->data.monadic->data.objref);
+ final_reg = outputReg ? tmpreg : ALLOC_FPR();
+
+ switch (nt) {
+ case EGREATER:
+ tmp = left;
+ left = right;
+ right = tmp;
+ case ELESS:
+ case ENOTEQU:
+ tmp = expr1;
+ expr1 = expr2;
+ expr2 = tmp;
+ flag2 = 1;
+ break;
+ case ELESSEQU:
+ tmp = left;
+ left = right;
+ right = tmp;
+ flag2 = 0;
+ break;
+ case EGREATEREQU:
+ case EEQU:
+ flag2 = 0;
+ break;
+ default:
+ CError_FATAL(3744);
+ }
+
+ if (ENODE_IS(left, EFLOATCONST) && CMach_FloatIsZero(left->data.floatval)) {
+ GEN_NODE(right, &op);
+ ENSURE_FPR(&op, right->rtype, 0);
+ flag = 1;
+ } else if (ENODE_IS(right, EFLOATCONST) && CMach_FloatIsZero(right->data.floatval)) {
+ GEN_NODE(left, &op);
+ ENSURE_FPR(&op, left->rtype, 0);
+ } else {
+ fp_binary_operator((type->size == 4) ? PC_FSUBS : PC_FSUB, left, right, 0, &op);
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ case ENOTEQU:
+ if (flag) {
+ GEN_NODE(expr1, &op1);
+ op3 = op1;
+ ENSURE_FPR(&op1, expr1->rtype, 0);
+
+ GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0);
+
+ fneg_reg = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg, op.reg);
+ fsel_reg = ALLOC_FPR();
+ emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg);
+ emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg);
+ } else {
+ GEN_NODE(expr1, &op1);
+ op3 = op1;
+ ENSURE_FPR(&op1, expr1->rtype, 0);
+
+ GEN_NODE_TO_FPR(expr2, &op2, expr2->rtype, 0);
+
+ fneg_reg = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg, op.reg);
+ fsel_reg = ALLOC_FPR();
+ emitpcode(PC_FSEL, fsel_reg, op.reg, op2.reg, op1.reg);
+ emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, fsel_reg);
+ }
+ break;
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ GEN_NODE(expr1, &op1);
+ GEN_NODE(expr2, &op2);
+ op3 = flag2 ? op2 : op1;
+
+ ENSURE_FPR(&op1, expr1->rtype, 0);
+ ENSURE_FPR(&op2, expr2->rtype, 0);
+
+ fneg_reg = op.reg;
+ if (flag) {
+ fneg_reg = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg, op.reg);
+ }
+
+ emitpcode(PC_FSEL, final_reg, fneg_reg, op2.reg, op1.reg);
+ break;
+ default:
+ CError_FATAL(2862);
+ }
+
+ if (op3.optype != OpndType_FPR)
+ store_fp(final_reg, &op3, type);
+
+ output->optype = OpndType_FPR;
+ output->reg = final_reg;
+ return;
+ }
+
+ if (TOC_use_isel(expr, 1)) {
+ Operand isel_op;
+ ENode *x;
+ ENode *y;
+ ENode *abs_expr;
+
+ memclrw(&isel_op, sizeof(Operand));
+ CError_ASSERT(3966, ENODE_IS(expr1, EINDIRECT));
+ CError_ASSERT(3968, ENODE_IS(expr1->data.monadic, EOBJREF));
+
+ if (CONDASS_is_ABS(cond, expr1, expr2)) {
+ if (ENODE_IS(cond->data.diadic.left, EASS))
+ GEN_NODE(cond->data.diadic.left, &isel_op);
+ else if (ENODE_IS(cond->data.diadic.right, EASS))
+ GEN_NODE(cond->data.diadic.right, &isel_op);
+
+ outputReg = OBJECT_REG(expr1->data.monadic->data.objref);
+ CError_ASSERT(3979, outputReg);
+
+ GEN_NODE(expr1, &op1);
+ op3 = op1;
+
+ CError_ASSERT(3986, op3.optype == OpndType_GPR && op3.reg == outputReg);
+
+ ENSURE_GPR(&op1, expr1->rtype, 0);
+ if (expr1->rtype->size < 4)
+ extend32(output, expr1->rtype, op3.reg);
+
+ reg1 = ALLOC_GPR();
+ reg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, reg1, op1.reg, 31);
+ emitpcode(PC_XOR, reg2, reg1, op1.reg);
+ emitpcode(PC_SUBF, outputReg, reg1, reg2);
+ output->optype = OpndType_GPR;
+ output->reg = op3.reg;
+
+ if (expr1->rtype->size < 4)
+ extend32(output, expr1->rtype, op3.reg);
+
+ return;
+ }
+ }
+
+ logical_expression(cond, label1, label2, label1);
+ branch_label(label1);
+ gen_ASS(expr, outputReg, outputRegHi, output);
+ branch_label(label2);
+}
+
+void gen_FUNCCALL(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ if (is_intrinsic_function_call(expr))
+ call_intrinsic_function(expr, outputReg, output);
+ else
+ call_function(expr, output);
+}
+
+void gen_OBJREF(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ symbol_operand(output, expr->data.objref);
+}
+
+void gen_UNEXPECTED(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ CError_FATAL(4160);
+}
+
+static int small(ENode *expr) {
+ Type *type;
+
+ type = expr->rtype;
+ if (!ENODE_IS(expr, ETYPCON))
+ return 0;
+
+ do {
+ expr = expr->data.monadic;
+ } while (ENODE_IS(expr, ETYPCON) && (type = expr->rtype)->size == 4);
+
+ return IS_TYPE_INT_OR_ENUM(type) && ((type->size < 2) || (type->size == 2 && !is_unsigned(type)));
+}
+
+void binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) {
+ Operand opleft;
+ Operand opright;
+ int reg;
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE_TO_GPR(right, &opright, right->rtype, 0);
+ GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0);
+ } else {
+ GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0);
+ GEN_NODE_TO_GPR(right, &opright, right->rtype, 0);
+ }
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (opcode == PC_MULLW && small(left))
+ emitpcode(opcode, reg, opright.reg, opleft.reg);
+ else
+ emitpcode(opcode, reg, opleft.reg, opright.reg);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void binary_immediate(Opcode opcode, ENode *left, SInt32 value, short outputReg, Operand *output) {
+ Operand opleft;
+ int reg;
+
+ memclrw(&opleft, sizeof(Operand));
+ GEN_NODE_TO_GPR(left, &opleft, left->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (opcode == PC_MULLI && value == 0)
+ emitpcode(PC_LI, reg, 0);
+ else if (opcode == PC_MULLI && value == 1)
+ emitpcode(PC_MR, reg, opleft.reg);
+ else
+ emitpcode(opcode, reg, opleft.reg, value);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+void unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(opcode, reg, op.reg);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void or_xor_immediate(Opcode opcode, ENode *expr, SInt32 value, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (expr->rtype->size > 2 && value != (value & 0xFFFF)) {
+ if (value & 0xFFFF) {
+ emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16);
+ emitpcode(opcode, reg, reg, value & 0xFFFF);
+ } else {
+ emitpcode((opcode == PC_ORI) ? PC_ORIS : PC_XORIS, reg, op.reg, value >> 16);
+ }
+ } else {
+ emitpcode(opcode, reg, op.reg, value & 0xFFFF);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void shift_left_immediate(ENode *expr, short shift, short negate, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ if (negate)
+ reg = ALLOC_GPR();
+ else
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ emitpcode(PC_RLWINM, reg, op.reg, shift & 31, 0, 31 - (shift & 31));
+
+ if (negate) {
+ int tmp = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, tmp, reg);
+ reg = tmp;
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void shift_right_immediate(ENode *expr, Type *type, short shift, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (is_unsigned(type))
+ emitpcode(PC_RLWINM, reg, op.reg, (32 - (shift & 31)) & 31, (shift & 31) + (32 - (type->size * 8)), 31);
+ else
+ emitpcode(PC_SRAWI, reg, op.reg, shift & 31);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void signed_divide_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+ int tmpreg1;
+ int tmpreg2;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ if (!copts.optimizesize && shift == 1) {
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31);
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_ADD, tmpreg2, tmpreg1, op.reg);
+ reg = (outputReg && !negate) ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, reg, tmpreg2, 1);
+ } else {
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg1, op.reg, shift);
+ reg = (outputReg && !negate) ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDZE, reg, tmpreg1);
+ }
+
+ if (negate) {
+ int prevreg = reg;
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, reg, prevreg);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void signed_mod_by_power_of_2(ENode *expr, int shift, int negate, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+ int tmpreg1;
+ int tmpreg2;
+ int tmpreg3;
+ int tmpreg4;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+
+ if (shift == 1) {
+ emitpcode(PC_RLWINM, tmpreg1, op.reg, 1, 31, 31);
+ emitpcode(PC_RLWINM, tmpreg2, op.reg, 0, 31, 31);
+ emitpcode(PC_XOR, tmpreg3, tmpreg2, tmpreg1);
+ emitpcode(PC_SUBF, reg, tmpreg1, tmpreg3);
+ } else {
+ tmpreg4 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpreg1, op.reg, 32 - shift, 0, 31 - (32 - shift));
+ emitpcode(PC_RLWINM, tmpreg2, op.reg, 1, 31, 31);
+ emitpcode(PC_SUBF, tmpreg3, tmpreg2, tmpreg1);
+ emitpcode(PC_RLWINM, tmpreg4, tmpreg3, shift, 0, 31);
+ emitpcode(PC_ADD, reg, tmpreg4, tmpreg2);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void fp_binary_operator(Opcode opcode, ENode *left, ENode *right, short outputReg, Operand *output) {
+ Operand opleft;
+ Operand opright;
+ int reg;
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE_TO_FPR(right, &opright, right->rtype, 0);
+ GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0);
+ } else {
+ GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0);
+ GEN_NODE_TO_FPR(right, &opright, right->rtype, 0);
+ }
+
+ reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(opcode, reg, opleft.reg, opright.reg);
+
+ output->optype = OpndType_FPR;
+ output->reg = reg;
+}
+
+void fp_unary_operator(Opcode opcode, ENode *expr, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(opcode, reg, op.reg);
+
+ output->optype = OpndType_FPR;
+ output->reg = reg;
+}
+
+void fp_multiply_add(Opcode opcode, ENode *a, ENode *b, ENode *c, short outputReg, Operand *output) {
+ Operand opA;
+ Operand opB;
+ Operand opC;
+ int reg;
+
+ memclrw(&opA, sizeof(Operand));
+ memclrw(&opB, sizeof(Operand));
+ memclrw(&opC, sizeof(Operand));
+
+ if (c->hascall) {
+ GEN_NODE_TO_FPR(c, &opC, c->rtype, 0);
+ if (b->hascall) {
+ GEN_NODE_TO_FPR(b, &opB, b->rtype, 0);
+ GEN_NODE_TO_FPR(a, &opA, a->rtype, 0);
+ } else {
+ GEN_NODE_TO_FPR(a, &opA, a->rtype, 0);
+ GEN_NODE_TO_FPR(b, &opB, b->rtype, 0);
+ }
+ } else {
+ if (b->hascall) {
+ GEN_NODE_TO_FPR(b, &opB, b->rtype, 0);
+ GEN_NODE_TO_FPR(a, &opA, a->rtype, 0);
+ GEN_NODE_TO_FPR(c, &opC, c->rtype, 0);
+ } else {
+ GEN_NODE_TO_FPR(a, &opA, a->rtype, 0);
+ GEN_NODE_TO_FPR(b, &opB, b->rtype, 0);
+ GEN_NODE_TO_FPR(c, &opC, c->rtype, 0);
+ }
+ }
+
+ reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(opcode, reg, opA.reg, opB.reg, opC.reg);
+
+ output->optype = OpndType_FPR;
+ output->reg = reg;
+}
+
+void gen_COMPARE(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ expr = evaluate_and_skip_comma(expr);
+ if (TYPE_IS_8BYTES(expr->data.diadic.right->rtype) || TYPE_IS_8BYTES(expr->data.diadic.left->rtype))
+ I8_gen_condition(expr, output, 1);
+ else
+ gen_condition_gpr(expr, output, outputReg);
+}
+
+void gen_LOGICAL(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ ENodeType op;
+
+ expr = evaluate_and_skip_comma(expr);
+ inner = evaluate_and_skip_comma(expr->data.monadic);
+ expr->data.monadic = inner;
+
+ if (ENODE_IS(expr, ELOGNOT) && !ENODE_IS2(inner, ELAND, ELOR)) {
+ op = inner->type;
+ if (ENODE_IS(inner, ELOGNOT)) {
+ switch (inner->data.monadic->type) {
+ case ELOGNOT:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ GEN_NODE(inner->data.monadic, output);
+ if (expr->data.monadic->rtype->size < 4)
+ extend32(output, expr->data.monadic->rtype, 0);
+ ENSURE_GPR(output, expr->data.monadic->rtype, 0);
+ return;
+ }
+ }
+
+ if (ENODE_IS(inner, ENOTEQU) && !TYPE_IS_8BYTES(inner->data.diadic.left->rtype) && ENODE_IS(inner->data.diadic.right, EINTCONST) && inner->data.diadic.right->data.intval.lo == 0) {
+ int tmpreg1;
+ int tmpreg2;
+ GEN_NODE(inner->data.diadic.left, output);
+ if (inner->data.diadic.left->rtype->size < 4)
+ extend32(output, inner->data.diadic.left->rtype, 0);
+ ENSURE_GPR(output, inner->data.diadic.left->rtype, 0);
+
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ CError_ASSERT(4853, output->optype == OpndType_GPR);
+
+ emitpcode(PC_CNTLZW, tmpreg2, output->reg);
+ emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = tmpreg1;
+ } else {
+ int tmpreg1;
+ int tmpreg2;
+ ENodeType inverted;
+
+ inverted = invert_relop(op);
+ if (op != inverted && !IS_TYPE_FLOAT(inner->data.diadic.left->rtype)) {
+ inner->type = inverted;
+ gen_COMPARE(inner, 0, 0, output);
+ inner->type = inverted;
+ return;
+ }
+
+ GEN_NODE(inner, output);
+ if (inner->rtype->size < 4)
+ extend32(output, inner->rtype, 0);
+ ENSURE_GPR(output, inner->rtype, 0);
+
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ CError_ASSERT(4883, output->optype == OpndType_GPR);
+
+ emitpcode(PC_CNTLZW, tmpreg2, output->reg);
+ emitpcode(PC_RLWINM, tmpreg1, tmpreg2, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = tmpreg1;
+ }
+ } else {
+ PCodeLabel *label1;
+ PCodeLabel *label2;
+ int tmpreg;
+
+ label1 = makepclabel();
+ label2 = makepclabel();
+
+ tmpreg = ALLOC_GPR();
+ emitpcode(PC_LI, tmpreg, 0);
+ logical_expression(expr, label1, label2, label1);
+ branch_label(label1);
+ emitpcode(PC_LI, tmpreg, 1);
+ branch_label(label2);
+ output->optype = OpndType_GPR;
+ output->reg = tmpreg;
+ }
+}
+
+void gen_NULLCHECK(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ PrecomputedOperand *precomp;
+ int flag;
+ int reg;
+ PCodeLabel *label;
+
+ left = expr->data.nullcheck.nullcheckexpr;
+ right = expr->data.nullcheck.condexpr;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+ flag = !IS_TYPE_VOID(expr->rtype) && !expr->ignored;
+
+ GEN_NODE(left, &opleft);
+ if (left->rtype->size < 4)
+ extend32(&opleft, left->rtype, 0);
+ ENSURE_GPR(&opleft, left->rtype, 0);
+
+ precomp = lalloc(sizeof(PrecomputedOperand));
+ precomp->precompid = expr->data.nullcheck.precompid;
+ precomp->operand = opleft;
+ precomp->next = precomputedoperands;
+ precomputedoperands = precomp;
+
+ emitpcode(PC_CMPI, 0, opleft.reg, 0);
+ if (flag) {
+ emitpcode(PC_MR, reg = ALLOC_GPR(), opleft.reg);
+ }
+
+ label = makepclabel();
+ branch_conditional(0, EEQU, 1, label);
+ GEN_NODE(right, &opright);
+ precomputedoperands = precomputedoperands->next;
+
+ if (flag) {
+ ENSURE_GPR(&opright, right->rtype, reg);
+ if (opright.reg != reg)
+ emitpcode(PC_MR, reg, opright.reg);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ }
+
+ branch_label(label);
+}
+
+void gen_PRECOMP(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ PrecomputedOperand *precomp;
+
+ for (precomp = precomputedoperands; precomp; precomp = precomp->next) {
+ if (precomp->precompid == expr->data.precompid)
+ break;
+ }
+
+ *output = precomp->operand;
+}
+
+void logical_expression(ENode *cond, PCodeLabel *if_true, PCodeLabel *if_false, PCodeLabel *end) {
+ PCodeLabel *label;
+ Operand op;
+ memclrw(&op, sizeof(Operand));
+
+ cond = evaluate_and_skip_comma(cond);
+ switch (cond->type) {
+ case ELAND:
+ label = makepclabel();
+ logical_expression(cond->data.diadic.left, label, if_false, label);
+ branch_label(label);
+ logical_expression(cond->data.diadic.right, if_true, if_false, end);
+ break;
+ case ELOR:
+ label = makepclabel();
+ logical_expression(cond->data.diadic.left, if_true, label, label);
+ branch_label(label);
+ logical_expression(cond->data.diadic.right, if_true, if_false, end);
+ break;
+ case ELOGNOT:
+ logical_expression(cond->data.monadic, if_false, if_true, end);
+ break;
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype))
+ I8_gen_condition(cond, &op, 0);
+ else
+ gen_condition(cond, &op);
+
+ if (end == if_true)
+ branch_conditional(op.reg, op.regOffset, 0, if_false);
+ else
+ branch_conditional(op.reg, op.regOffset, 1, if_true);
+ break;
+ default:
+ CError_FATAL(5160);
+ }
+}
+
+static void logical_expression_nobranch(ENode *cond, Boolean invert, Operand *output) {
+ cond = evaluate_and_skip_comma(cond);
+ switch (cond->type) {
+ case ELOGNOT:
+ logical_expression_nobranch(cond->data.monadic, 1, output);
+ break;
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ if (invert) {
+ ENodeType nt = invert_relop(cond->type);
+ CError_ASSERT(5190, nt != cond->type);
+ cond->type = nt;
+ }
+
+ if (TYPE_IS_8BYTES(cond->data.diadic.right->rtype) || TYPE_IS_8BYTES(cond->data.diadic.left->rtype))
+ I8_gen_condition(cond, output, 0);
+ else
+ gen_condition(cond, output);
+
+ break;
+ default:
+ CError_FATAL(5206);
+ }
+}
+
+static ENodeType invert_relop(ENodeType nt) {
+ switch (nt) {
+ case ELESS: return EGREATEREQU;
+ case EGREATER: return ELESSEQU;
+ case ELESSEQU: return EGREATER;
+ case EGREATEREQU: return ELESS;
+ case EEQU: return ENOTEQU;
+ case ENOTEQU: return EEQU;
+ default: return nt;
+ }
+}
+
+static int reverse_relop(int nt) {
+ switch (nt) {
+ case ELESS: return EGREATER;
+ case EGREATER: return ELESS;
+ case ELESSEQU: return EGREATEREQU;
+ case EGREATEREQU: return ELESSEQU;
+ default: return nt;
+ }
+}
+
+void gen_condition(ENode *cond, Operand *output) {
+ ENode *left;
+ ENode *right;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ if (IS_TYPE_FLOAT(left->rtype)) {
+ compare_floating(cond->type, left, right, output);
+ return;
+ }
+
+ if (ENODE_IS(right, EINTCONST)) {
+ if (is_unsigned(left->rtype)) {
+ UInt32 val = right->data.intval.lo;
+ if (FITS_IN_USHORT(val)) {
+ compare_immediate(cond->type, left, val, output);
+ return;
+ } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) {
+ compare_immediate_long(cond->type, left, val, output);
+ return;
+ }
+ } else {
+ UInt32 val = right->data.intval.lo;
+ if (FITS_IN_SHORT(val)) {
+ compare_immediate(cond->type, left, val, output);
+ return;
+ } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) {
+ compare_immediate_long(cond->type, left, val, output);
+ return;
+ }
+ }
+ } else if (ENODE_IS(left, EINTCONST)) {
+ if (is_unsigned(right->rtype)) {
+ UInt32 val = left->data.intval.lo;
+ if (FITS_IN_USHORT(val)) {
+ compare_immediate(reverse_relop(cond->type), right, val, output);
+ return;
+ } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) {
+ compare_immediate_long(reverse_relop(cond->type), right, val, output);
+ return;
+ }
+ } else {
+ UInt32 val = left->data.intval.lo;
+ if (FITS_IN_SHORT(val)) {
+ compare_immediate(reverse_relop(cond->type), right, val, output);
+ return;
+ } else if (ENODE_IS2(cond, EEQU, ENOTEQU)) {
+ compare_immediate_long(reverse_relop(cond->type), right, val, output);
+ return;
+ }
+ }
+ }
+
+ compare_integer(cond->type, left, right, output);
+}
+
+void gen_condition_gpr(ENode *cond, Operand *output, short outputReg) {
+ ENode *left;
+ ENode *right;
+ Operand condOp;
+ int finalReg;
+ int tmpReg;
+ int tmpReg2;
+ int tmpReg3;
+ int tmpReg4;
+ int a;
+ int b;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ memclrw(&condOp, sizeof(Operand));
+
+ if (!IS_TYPE_FLOAT(left->rtype)) {
+ Operand op1;
+ Operand op2;
+ Operand opTmp;
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+ memclrw(&opTmp, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+
+ GEN_NODE(left, &op1);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 0);
+ } else if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ } else if (value == 1) {
+ emitpcode(
+ PC_RLWINM, finalReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ } else {
+ CError_FATAL(5434);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg, op1.reg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ case ENOTEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 1);
+ } else if (value == 0) {
+ emitpcode(
+ PC_RLWINM, finalReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ } else if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ } else {
+ CError_FATAL(5503);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg, op1.reg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, op1.reg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op2.reg, op1.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATEREQU:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESSEQU:
+ if (is_unsigned(left->rtype)) {
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_LI, tmpReg, -1);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg2, op1.reg, op2.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFZE, finalReg, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ORC, tmpReg2, op2.reg, op1.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg3, tmpReg, 31, 1, 31);
+ tmpReg4 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_LI, tmpReg, 1);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWNM, finalReg, tmpReg, tmpReg2, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, op2.reg, 31);
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg3, op1.reg, op2.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDE, finalReg, tmpReg2, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATER:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg2, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESS:
+ if (is_unsigned(left->rtype)) {
+ if (left->rtype->size <= 2) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ } else {
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFE, tmpReg2, tmpReg, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, finalReg, tmpReg2);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_SLW, tmpReg3, op2.reg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg3, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, op1.reg, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XOR, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_AND, tmpReg3, tmpReg, op2.reg);
+ tmpReg4 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, finalReg, tmpReg4, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ default:
+ CError_FATAL(5777);
+ }
+ }
+
+ gen_condition(cond, &condOp);
+ emitpcode(PC_MFCR, tmpReg = used_virtual_registers[RegClass_GPR]++);
+ a = 0;
+ b = condOp.reg * 4;
+ switch (condOp.regOffset) {
+ case ENOTEQU:
+ a = 1;
+ case EEQU:
+ b += 2;
+ break;
+ case EGREATEREQU:
+ a = 1;
+ break;
+ case ELESSEQU:
+ a = 1;
+ case EGREATER:
+ b += 1;
+ break;
+ }
+
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ if (a) {
+ emitpcode(PC_RLWINM, tmpReg, tmpReg, b + 1, 31, 31);
+ emitpcode(PC_XORI, finalReg, tmpReg, 1);
+ } else {
+ emitpcode(PC_RLWINM, finalReg, tmpReg, b + 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+}
+
+void gen_negated_condition_gpr(ENode *cond, Operand *output, short outputReg) {
+ ENode *left;
+ ENode *right;
+ Operand op1;
+ Operand op2;
+ Operand opTmp;
+ int finalReg;
+ int tmpReg;
+ int tmpReg2;
+ int tmpReg3;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ CError_ASSERT(5843, TYPE_FITS_IN_REGISTER(left->rtype) && TYPE_FITS_IN_REGISTER(right->rtype));
+
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+ memclrw(&opTmp, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+
+ GEN_NODE(left, &op1);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &op1);
+ ENSURE_GPR(&op1, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&op1, left->rtype, 0);
+
+ GEN_NODE(right, &op2);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op2, right->rtype, 0);
+ ENSURE_GPR(&op2, right->rtype, 0);
+ }
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, 0);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM,
+ tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31,
+ 31,
+ 31);
+ emitpcode(PC_NEG, finalReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = tmpReg; // bug???
+ return;
+ }
+
+ CError_FATAL(5923);
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg, op1.reg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg2, tmpReg, 27, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, finalReg, tmpReg2);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_NOR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg3, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case ENOTEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op == PC_RLWINM &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op1.reg
+ )
+ {
+ PCode *pc = pclastblock->lastPCode;
+ SInt32 a = pc->args[2].data.imm.value;
+ SInt32 b = pc->args[3].data.imm.value;
+ SInt32 value = right->data.intval.lo;
+ if (b == pc->args[4].data.imm.value) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+
+ if (value != (value & 1)) {
+ emitpcode(PC_LI, finalReg, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 0) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_NEG, finalReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (value == 1) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpReg,
+ pc->args[1].data.reg.reg,
+ (a + b + 1) & 31, 31, 31);
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ CError_FATAL(6031);
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFIC, tmpReg, op1.reg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (copts.optimizesize) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFIC, tmpReg2, tmpReg, 0);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg2, tmpReg2);
+ } else {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg3, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATEREQU:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, -1);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESSEQU:
+ if (is_unsigned(left->rtype)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op1.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDZE, tmpReg2, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBF, finalReg, tmpReg2, op1.reg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ORC, tmpReg2, op1.reg, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XORIS, tmpReg, op1.reg, 0x8000);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op1.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_ADDC, tmpReg3, tmpReg2, tmpReg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg3);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ case EGREATER:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ANDC, tmpReg2, tmpReg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, tmpReg2, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+ opTmp = op2;
+ op2 = op1;
+ op1 = opTmp;
+
+ case ELESS:
+ if (is_unsigned(left->rtype)) {
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SRAWI, finalReg, op1.reg, 31);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+ }
+
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op2.reg, op1.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg2, op2.reg, 1, 31, 31);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg3, op1.reg, 1, 31, 31);
+ finalReg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, finalReg, tmpReg3, tmpReg2);
+ output->optype = OpndType_GPR;
+ output->reg = finalReg;
+ return;
+
+ default:
+ CError_FATAL(6240);
+ }
+}
+
+void compare_floating(short nt, ENode *left, ENode *right, Operand *output) {
+ Operand opleft;
+ Operand opright;
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE_TO_FPR(right, &opright, right->rtype, 0);
+ GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0);
+ } else {
+ GEN_NODE_TO_FPR(left, &opleft, left->rtype, 0);
+ GEN_NODE_TO_FPR(right, &opright, right->rtype, 0);
+ }
+
+ emitpcode((nt == EEQU || nt == ENOTEQU) ? PC_FCMPU : PC_FCMPO, 0, opleft.reg, opright.reg);
+ if (nt == ELESSEQU) {
+ emitpcode(PC_CROR, 0, 2, 0, 0, 0, 2);
+ nt = EEQU;
+ } else if (nt == EGREATEREQU) {
+ emitpcode(PC_CROR, 0, 2, 0, 1, 0, 2);
+ nt = EEQU;
+ }
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
+}
+
+void compare_integer(short nt, ENode *left, ENode *right, Operand *output) {
+ Operand opleft;
+ Operand opright;
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (right->rtype->size < 4)
+ extend32(&opright, right->rtype, 0);
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ GEN_NODE(left, &opleft);
+ if (left->rtype->size < 4)
+ extend32(&opleft, left->rtype, 0);
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&opleft, left->rtype, 0);
+
+ GEN_NODE(right, &opright);
+ if (right->rtype->size < 4)
+ extend32(&opright, right->rtype, 0);
+ ENSURE_GPR(&opright, right->rtype, 0);
+ }
+
+ emitpcode(is_unsigned(left->rtype) ? PC_CMPL : PC_CMP, 0, opleft.reg, opright.reg);
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
+}
+
+void compare_immediate(short nt, ENode *left, SInt32 value, Operand *output) {
+ int postIncFlag;
+ short postIncReg;
+ Operand op;
+ SInt32 postIncValue;
+
+ memclrw(&op, sizeof(Operand));
+
+ postIncFlag = ispostincrementopportunity(left, &op, &postIncValue);
+ if (!postIncFlag) {
+ GEN_NODE(left, &op);
+ if (op.optype != OpndType_CRField) {
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ else
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+ } else {
+ postIncReg = op.reg;
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+
+ if (op.optype == OpndType_CRField) {
+ if (
+ (nt == EEQU && value == 1) ||
+ (nt == ENOTEQU && value == 0) ||
+ (nt == EGREATER && value == 0) ||
+ (nt == EGREATEREQU && value == 1)
+ )
+ {
+ *output = op;
+ return;
+ }
+
+ if (
+ (nt == EEQU && value == 0) ||
+ (nt == ENOTEQU && value == 1) ||
+ (nt == ELESS && value == 1) ||
+ (nt == ELESSEQU && value == 0)
+ )
+ {
+ *output = op;
+ switch (op.regOffset) {
+ case EEQU:
+ output->regOffset = ENOTEQU;
+ return;
+ case ENOTEQU:
+ output->regOffset = EEQU;
+ return;
+ case ELESS:
+ output->regOffset = EGREATEREQU;
+ return;
+ case EGREATER:
+ output->regOffset = ELESSEQU;
+ return;
+ case ELESSEQU:
+ output->regOffset = EGREATER;
+ return;
+ case EGREATEREQU:
+ output->regOffset = ELESS;
+ return;
+ }
+ }
+
+ ENSURE_GPR(&op, left->rtype, 0);
+ }
+
+ if (
+ copts.peephole &&
+ value == 0 &&
+ pclastblock->pcodeCount > 0 &&
+ pclastblock->lastPCode->op != PC_RLWINM &&
+ (PCODE_FLAG_SET_F(pclastblock->lastPCode) & (fIsMove | fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) &&
+ pclastblock->lastPCode->args[0].data.reg.reg == op.reg &&
+ (!is_unsigned(left->rtype) || nt == EEQU || nt == ENOTEQU)
+ )
+ {
+ pcsetrecordbit(pclastblock->lastPCode);
+ } else {
+ emitpcode(is_unsigned(left->rtype) ? PC_CMPLI : PC_CMPI, 0, op.reg, value);
+ }
+
+ if (postIncFlag)
+ add_register_immediate(postIncReg, postIncReg, postIncValue);
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
+}
+
+void compare_immediate_long(short nt, ENode *left, SInt32 value, Operand *output) {
+ int postIncFlag;
+ short postIncReg;
+ int outputReg;
+ Operand op;
+ SInt32 postIncValue;
+
+ memclrw(&op, sizeof(Operand));
+
+ postIncFlag = ispostincrementopportunity(left, &op, &postIncValue);
+ if (!postIncFlag) {
+ GEN_NODE(left, &op);
+ } else {
+ postIncReg = op.reg;
+ }
+
+ if (left->rtype->size < 4)
+ extend32(&op, left->rtype, 0);
+ ENSURE_GPR(&op, left->rtype, 0);
+
+ outputReg = ALLOC_GPR();
+ emitpcode(PC_ADDIS, outputReg, op.reg, 0, (SInt16) (~(value >> 16) + 1));
+ emitpcode(PC_CMPLI, 0, outputReg, value & 0xFFFF);
+
+ if (postIncFlag)
+ add_register_immediate(postIncReg, postIncReg, postIncValue);
+
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = nt;
+}
+
+static int ismask(SInt32 value, short *first, short *last) {
+ int start, end, bit;
+ start = end = -1;
+ for (bit = 31; bit >= 0; bit--) {
+ if (value & 1) {
+ if (start != -1)
+ return 0;
+ if (end == -1)
+ end = bit;
+ } else {
+ if (end != -1 && start == -1)
+ start = bit + 1;
+ }
+ value >>= 1;
+ }
+
+ if (end == -1)
+ return 0;
+ if (start == -1)
+ start = 0;
+ *first = start;
+ *last = end;
+ return 1;
+}
+
+int ismaskconstant(SInt32 value, short *first, short *last) {
+ short my_first;
+ short my_last;
+ if (ismask(value, first, last))
+ return 1;
+
+ if (value && ismask(~value, &my_first, &my_last)) {
+ *first = my_last + 1;
+ *last = my_first - 1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void shift_and_mask(ENode *expr, short a, short b, short c, short outputReg, Operand *output) {
+ Operand op;
+ int reg;
+
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE(expr, &op);
+ ENSURE_GPR(&op, expr->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, op.reg, a, b, c);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+int ispostincrementopportunity(ENode *expr, Operand *op, SInt32 *value) {
+ Type *type;
+ int reg;
+
+ type = expr->rtype;
+ if (!ENODE_IS2(expr, EPOSTINC, EPOSTDEC))
+ return 0;
+ if (!ENODE_IS(expr->data.monadic, EINDIRECT))
+ return 0;
+ if (!ENODE_IS(expr->data.monadic->data.monadic, EOBJREF))
+ return 0;
+
+ reg = OBJECT_REG(expr->data.monadic->data.monadic->data.objref);
+ if (!reg)
+ return 0;
+
+ if (IS_TYPE_POINTER(type)) {
+ if (ENODE_IS(expr, EPOSTINC))
+ *value = TPTR_TARGET(type)->size;
+ else
+ *value = -TPTR_TARGET(type)->size;
+ } else {
+ if (ENODE_IS(expr, EPOSTINC))
+ *value = 1;
+ else
+ *value = -1;
+ }
+
+ op->optype = OpndType_GPR;
+ op->reg = reg;
+ return 1;
+}
+
+void add_register_immediate(short regA, short regB, SInt32 value) {
+ if (!FITS_IN_SHORT(value)) {
+ emitpcode(PC_ADDIS, regA, regB, 0, HIGH_PART(value));
+ if (LOW_PART(value))
+ emitpcode(PC_ADDI, regA, regA, 0, LOW_PART(value));
+ } else {
+ emitpcode(PC_ADDI, regA, regB, 0, value);
+ }
+}
+
+static int ispowerof2(SInt32 val) {
+ int bit = getbit(val);
+ return (bit > 0 && bit < 31) ? bit : 0;
+}
+
+void I8_gen_ADD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ int is_uns;
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ short tmpreg1;
+ short tmpreg2;
+ SInt32 skipleft;
+ SInt32 skipright;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+ }
+
+ reg = ALLOC_GPR();
+ regHi = ALLOC_GPR();
+ is_uns = is_unsigned(expr->rtype) != 0;
+ skipleft = GetSizeSkip(left);
+ skipright = GetSizeSkip(right);
+
+ if (skipleft < skipright) {
+ Operand tmpop;
+ SInt32 tmp;
+
+ expr->data.diadic.left = right;
+ expr->data.diadic.right = left;
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+
+ tmpop = opright;
+ opright = opleft;
+ opleft = tmpop;
+
+ tmp = skipleft;
+ skipleft = skipright;
+ skipright = tmp;
+ }
+
+ switch (skipleft + skipright) {
+ case 1 + 1:
+ case 1 + 2:
+ case 2 + 2:
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) {
+ emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ } else {
+ emitpcode(PC_ADDC, reg, opleft.reg, opright.reg);
+ }
+ if (is_uns)
+ emitpcode(PC_LI, regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, reg, 31);
+ break;
+ case 1 + 4:
+ case 2 + 4:
+ case 4 + 4:
+ if (!is_uns) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31);
+ emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31);
+ }
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) {
+ emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ } else {
+ emitpcode(PC_ADDC, reg, opleft.reg, opright.reg);
+ }
+ if (is_uns) {
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_LI, tmpreg1, 0);
+ emitpcode(PC_ADDZE, regHi, tmpreg1);
+ } else {
+ emitpcode(PC_ADDE, regHi, tmpreg1, tmpreg2);
+ }
+ break;
+ case 1 + 8:
+ case 2 + 8:
+ case 4 + 8:
+ CError_ASSERT(6933, skipleft == 8);
+ if (!is_uns) {
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg2, opright.reg, 31);
+ }
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) {
+ emitpcode(PC_ADDIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) {
+ emitpcode(PC_ADDIC, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ } else {
+ emitpcode(PC_ADDC, reg, opleft.reg, opright.reg);
+ }
+ if (is_uns)
+ emitpcode(PC_ADDZE, regHi, opleft.regHi);
+ else
+ emitpcode(PC_ADDE, regHi, opleft.regHi, tmpreg2);
+ break;
+ case 8 + 8:
+ emitpcode(PC_ADDC, reg, opleft.reg, opright.reg);
+ emitpcode(PC_ADDE, regHi, opleft.regHi, opright.regHi);
+ break;
+ default:
+ CError_FATAL(6979);
+ }
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_INTCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ short reg;
+ short regHi;
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ load_immediate(reg, expr->data.intval.lo);
+ load_immediate(regHi, expr->data.intval.hi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_SUB(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ int is_uns;
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ short tmpreg1;
+ short tmpreg2;
+ short tmpreg3;
+ SInt32 skipleft;
+ SInt32 skipright;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+ }
+
+ reg = ALLOC_GPR();
+ regHi = ALLOC_GPR();
+ is_uns = is_unsigned(expr->rtype) != 0;
+ skipleft = GetSizeSkip(left);
+ skipright = GetSizeSkip(right);
+
+ switch (skipleft + skipright) {
+ case 1 + 1:
+ case 1 + 2:
+ case 2 + 2:
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else {
+ emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg);
+ }
+ if (is_uns)
+ emitpcode(PC_LI, regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, reg, 31);
+ break;
+ case 1 + 4:
+ case 2 + 4:
+ case 4 + 4:
+ if (!is_uns) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg2, opleft.reg, 31);
+ emitpcode(PC_SRAWI, tmpreg1, opright.reg, 31);
+ }
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else {
+ emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg);
+ }
+ if (is_uns) {
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_LI, tmpreg1, 0);
+ emitpcode(PC_SUBFZE, regHi, tmpreg1);
+ } else {
+ emitpcode(PC_SUBFE, regHi, tmpreg1, tmpreg2);
+ }
+ break;
+ case 1 + 8:
+ case 2 + 8:
+ case 4 + 8:
+ if (skipleft < skipright) {
+ emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg);
+ emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi);
+ } else {
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) {
+ emitpcode(PC_SUBFIC, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else {
+ emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg);
+ }
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_LI, tmpreg1, 0);
+ emitpcode(PC_SUBFE, regHi, tmpreg1, opleft.regHi);
+ }
+ break;
+ case 8 + 8:
+ emitpcode(PC_SUBFC, reg, opright.reg, opleft.reg);
+ emitpcode(PC_SUBFE, regHi, opright.regHi, opleft.regHi);
+ break;
+ default:
+ CError_FATAL(7211);
+ }
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7254, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_XOR, reg, opleft.reg, opright.reg);
+ emitpcode(PC_XOR, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7304, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_OR, reg, opleft.reg, opright.reg);
+ emitpcode(PC_OR, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ Operand opleft;
+ Operand opright;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ } else {
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ }
+
+ CError_ASSERT(7354, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+
+ emitpcode(PC_AND, reg, opleft.reg, opright.reg);
+ emitpcode(PC_AND, regHi, opleft.regHi, opright.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+int I8_getbit(UInt64 val) {
+ switch (val) {
+ case 0: return -1;
+ case 1ULL << 0: return 0;
+ case 1ULL << 1: return 1;
+ case 1ULL << 2: return 2;
+ case 1ULL << 3: return 3;
+ case 1ULL << 4: return 4;
+ case 1ULL << 5: return 5;
+ case 1ULL << 6: return 6;
+ case 1ULL << 7: return 7;
+ case 1ULL << 8: return 8;
+ case 1ULL << 9: return 9;
+ case 1ULL << 10: return 10;
+ case 1ULL << 11: return 11;
+ case 1ULL << 12: return 12;
+ case 1ULL << 13: return 13;
+ case 1ULL << 14: return 14;
+ case 1ULL << 15: return 15;
+ case 1ULL << 16: return 16;
+ case 1ULL << 17: return 17;
+ case 1ULL << 18: return 18;
+ case 1ULL << 19: return 19;
+ case 1ULL << 20: return 20;
+ case 1ULL << 21: return 21;
+ case 1ULL << 22: return 22;
+ case 1ULL << 23: return 23;
+ case 1ULL << 24: return 24;
+ case 1ULL << 25: return 25;
+ case 1ULL << 26: return 26;
+ case 1ULL << 27: return 27;
+ case 1ULL << 28: return 28;
+ case 1ULL << 29: return 29;
+ case 1ULL << 30: return 30;
+ case 1ULL << 31: return 31;
+ case 1ULL << 32: return 32;
+ case 1ULL << 33: return 33;
+ case 1ULL << 34: return 34;
+ case 1ULL << 35: return 35;
+ case 1ULL << 36: return 36;
+ case 1ULL << 37: return 37;
+ case 1ULL << 38: return 38;
+ case 1ULL << 39: return 39;
+ case 1ULL << 40: return 40;
+ case 1ULL << 41: return 41;
+ case 1ULL << 42: return 42;
+ case 1ULL << 43: return 43;
+ case 1ULL << 44: return 44;
+ case 1ULL << 45: return 45;
+ case 1ULL << 46: return 46;
+ case 1ULL << 47: return 47;
+ case 1ULL << 48: return 48;
+ case 1ULL << 49: return 49;
+ case 1ULL << 50: return 50;
+ case 1ULL << 51: return 51;
+ case 1ULL << 52: return 52;
+ case 1ULL << 53: return 53;
+ case 1ULL << 54: return 54;
+ case 1ULL << 55: return 55;
+ case 1ULL << 56: return 56;
+ case 1ULL << 57: return 57;
+ case 1ULL << 58: return 58;
+ case 1ULL << 59: return 59;
+ case 1ULL << 60: return 60;
+ case 1ULL << 61: return 61;
+ case 1ULL << 62: return 62;
+ case 1ULL << 63: return 63;
+ default: return -2;
+ }
+}
+
+int I8_log2n(UInt64 val) {
+ int bit = I8_getbit(val);
+ return (bit > 0 && bit < 63) ? bit : 0;
+}
+
+void I8_ShiftLeftImmediate(Operand opnd, SInt32 value, int is_unsigned, SInt32 size, short reg, short regHi) {
+ if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg)
+ CError_FATAL(7703);
+
+ if (value < 32) {
+ emitpcode(PC_RLWINM, reg, opnd.reg, value, 0, 31 - value);
+ if (size > 4) {
+ emitpcode(PC_RLWINM, regHi, opnd.regHi, value, 0, 31 - value);
+ emitpcode(PC_RLWIMI, regHi, opnd.reg, value, 32 - value, 31);
+ } else {
+ emitpcode(PC_RLWINM, regHi, opnd.reg, value, 32 - value, 31);
+ }
+ } else if (value <= 63) {
+ if (value == 32)
+ emitpcode(PC_MR, regHi, opnd.reg);
+ else
+ emitpcode(PC_RLWINM, regHi, opnd.reg, value - 32, 0, 63 - value);
+ emitpcode(PC_LI, reg, 0);
+ } else {
+ CError_FATAL(7732);
+ }
+}
+
+void I8_ShiftRightImmediate(Operand opnd, SInt32 value, int is_unsigned, short reg, short regHi, int unk) {
+ short tmpreg1;
+ short tmpreg2;
+ short tmpreg3;
+ short tmpreg4;
+
+ if (opnd.reg == reg || opnd.regHi == regHi || opnd.reg == regHi || opnd.regHi == reg)
+ CError_FATAL(7756);
+
+ if (value < 32) {
+ emitpcode(PC_RLWINM, reg, opnd.reg, 32 - value, 0, 31);
+ emitpcode(PC_RLWIMI, reg, opnd.regHi, 32 - value, 0, value - 1);
+ if (is_unsigned) {
+ emitpcode(PC_RLWINM, regHi, opnd.regHi, 32 - value, value, 31);
+ } else if (unk) {
+ tmpreg1 = ALLOC_GPR();
+ emitpcode(PC_MR, tmpreg1, opnd.regHi);
+ emitpcode(PC_RLWIMI, tmpreg1, opnd.reg, 0, 31 - (value - 1), 31);
+ emitpcode(PC_SRAWI, regHi, tmpreg1, value);
+ } else {
+ emitpcode(PC_SRAWI, regHi, opnd.regHi, value);
+ }
+ } else if (value == 32) {
+ if (is_unsigned) {
+ emitpcode(PC_MR, reg, opnd.regHi);
+ emitpcode(PC_LI, regHi, 0);
+ } else if (unk) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpreg1, opnd.reg);
+ emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg);
+ emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31);
+ emitpcode(PC_RLWIMI, tmpreg3, opnd.regHi, 0, 0, 0);
+ emitpcode(PC_MR, reg, opnd.regHi);
+ emitpcode(PC_SRAWI, regHi, value, 31);
+ } else {
+ emitpcode(PC_MR, reg, opnd.regHi);
+ emitpcode(PC_SRAWI, regHi, opnd.regHi, 31);
+ }
+ } else if (value <= 63) {
+ if (is_unsigned) {
+ emitpcode(PC_RLWINM, reg, opnd.regHi, 64 - value, value - 32, 31);
+ emitpcode(PC_LI, regHi, 0);
+ } else if (unk) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpreg1, opnd.reg);
+ emitpcode(PC_OR, tmpreg2, tmpreg1, opnd.reg);
+ emitpcode(PC_RLWINM, tmpreg3, tmpreg2, 1, 31, 31);
+ emitpcode(PC_OR, tmpreg4, opnd.regHi, tmpreg3);
+ emitpcode(PC_SRAWI, regHi, opnd.regHi, 31);
+ emitpcode(PC_SRAWI, reg, tmpreg4, value - 32);
+ } else {
+ emitpcode(PC_SRAWI, reg, opnd.regHi, value - 32);
+ emitpcode(PC_SRAWI, regHi, opnd.regHi, 31);
+ }
+ } else {
+ CError_FATAL(7866);
+ }
+}
+
+void I8_gen_MUL(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ int is_uns;
+ ENode *left;
+ ENode *right;
+ short reg;
+ short regHi;
+ short tmpreg1;
+ short tmpreg2;
+ short tmpreg3;
+ short tmpreg4;
+ SInt32 skipleft;
+ SInt32 skipright;
+ Operand opleft;
+ Operand opright;
+ SInt64 leftval;
+ SInt64 rightval;
+ int shift;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+ skipleft = GetSizeSkip(left);
+ skipright = GetSizeSkip(right);
+
+ if (ENODE_IS(right, EINTCONST) && ENODE_IS(left, EINTCONST))
+ CError_FATAL(7900);
+
+ if (ENODE_IS(left, EINTCONST))
+ leftval = left->data.intval.lo + (((SInt64) ((skipleft < 8) ? 0 : left->data.intval.hi)) << 32);
+ if (ENODE_IS(right, EINTCONST))
+ rightval = right->data.intval.lo + (((SInt64) ((skipright < 8) ? 0 : right->data.intval.hi)) << 32);
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) {
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ }
+ } else {
+ if (!(ENODE_IS(left, EINTCONST) && I8_log2n(leftval) > 0)) {
+ GEN_NODE(left, &opleft);
+ if (TYPE_IS_8BYTES(left->rtype))
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ }
+
+ if (!(ENODE_IS(right, EINTCONST) && I8_log2n(rightval) > 0)) {
+ GEN_NODE(right, &opright);
+ if (TYPE_IS_8BYTES(right->rtype))
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+ else
+ ENSURE_GPR(&opright, right->rtype, 0);
+ }
+ }
+
+ is_uns = is_unsigned(expr->rtype) != 0;
+
+ if (skipleft < skipright) {
+ Operand tmpop;
+ SInt64 tmp64;
+ SInt32 tmp;
+
+ expr->data.diadic.left = right;
+ expr->data.diadic.right = left;
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+
+ tmpop = opright;
+ opright = opleft;
+ opleft = tmpop;
+
+ tmp64 = leftval;
+ leftval = rightval;
+ rightval = tmp64;
+
+ tmp = skipleft;
+ skipleft = skipright;
+ skipright = tmp;
+ }
+
+ reg = ALLOC_GPR();
+ regHi = ALLOC_GPR();
+
+ if (ENODE_IS(left, EINTCONST) && (shift = I8_log2n(leftval)) > 0) {
+ I8_ShiftLeftImmediate(opright, shift, is_uns, skipright, reg, regHi);
+ } else if (ENODE_IS(right, EINTCONST) && (shift = I8_log2n(rightval)) > 0) {
+ I8_ShiftLeftImmediate(opleft, shift, is_uns, skipleft, reg, regHi);
+ } else {
+ switch (skipleft + skipright) {
+ case 1 + 1:
+ case 1 + 2:
+ case 2 + 2:
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) {
+ emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ } else {
+ emitpcode(PC_MULLW, reg, opleft.reg, opright.reg);
+ }
+ if (is_uns)
+ emitpcode(PC_LI, regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, reg, 31);
+ break;
+ case 1 + 4:
+ case 2 + 4:
+ case 4 + 4:
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo)) {
+ emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo)) {
+ emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ } else {
+ emitpcode(PC_MULLW, reg, opleft.reg, opright.reg);
+ }
+ if (is_uns)
+ emitpcode(PC_MULHWU, regHi, opleft.reg, opright.reg);
+ else
+ emitpcode(PC_MULHW, regHi, opleft.reg, opright.reg);
+ break;
+ case 1 + 8:
+ case 2 + 8:
+ case 4 + 8:
+ CError_ASSERT(8097, skipleft == 8);
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) {
+ emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ if (is_uns)
+ emitpcode(PC_MULHWU, regHi, opright.reg, opleft.reg);
+ else
+ emitpcode(PC_MULHW, regHi, opright.reg, opleft.reg);
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ if (is_uns) {
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo));
+ emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1);
+ } else {
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31);
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLI, tmpreg1, opleft.regHi, LOW_PART(right->data.intval.lo));
+ emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4);
+ emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1);
+ emitpcode(PC_ADD, regHi, regHi, tmpreg3);
+ }
+ } else {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ if (is_uns) {
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg);
+ emitpcode(PC_MULLW, reg, opleft.reg, opright.reg);
+ emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1);
+ } else {
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpreg4, opright.reg, 31);
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg);
+ emitpcode(PC_MULLW, reg, opleft.reg, opright.reg);
+ emitpcode(PC_MULLW, tmpreg3, opleft.reg, tmpreg4);
+ emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1);
+ emitpcode(PC_ADD, regHi, regHi, tmpreg3);
+ }
+ }
+ break;
+ case 8 + 8:
+ if (ENODE_IS(left, EINTCONST) && FITS_IN_SHORT2(left->data.intval.lo) && left->data.intval.hi == 0) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_MULHWU, tmpreg1, opright.reg, opleft.reg);
+ emitpcode(PC_MULLW, tmpreg2, opright.reg, opleft.regHi);
+ emitpcode(PC_MULLI, reg, opright.reg, LOW_PART(left->data.intval.lo));
+ emitpcode(PC_ADD, regHi, tmpreg1, tmpreg2);
+ } else if (ENODE_IS(right, EINTCONST) && FITS_IN_SHORT2(right->data.intval.lo) && right->data.intval.hi == 0) {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg);
+ emitpcode(PC_MULLI, reg, opleft.reg, LOW_PART(right->data.intval.lo));
+ emitpcode(PC_ADD, regHi, tmpreg2, tmpreg1);
+ } else {
+ tmpreg1 = ALLOC_GPR();
+ tmpreg2 = ALLOC_GPR();
+ tmpreg3 = ALLOC_GPR();
+ tmpreg4 = ALLOC_GPR();
+ emitpcode(PC_MULHWU, tmpreg2, opleft.reg, opright.reg);
+ emitpcode(PC_MULLW, tmpreg1, opleft.regHi, opright.reg);
+ emitpcode(PC_ADD, tmpreg3, tmpreg2, tmpreg1);
+ emitpcode(PC_MULLW, tmpreg4, opleft.reg, opright.regHi);
+ emitpcode(PC_MULLW, reg, opleft.reg, opright.reg);
+ emitpcode(PC_ADD, regHi, tmpreg3, tmpreg4);
+ }
+ break;
+ default:
+ CError_FATAL(8218);
+ }
+ }
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_BINNOT(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Operand op;
+ int reg;
+ int regHi;
+
+ inner = expr->data.monadic;
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE(inner, &op);
+ coerce_to_register_pair(&op, inner->rtype, 0, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+ emitpcode(PC_NOR, reg, op.reg, op.reg);
+ emitpcode(PC_NOR, regHi, op.regHi, op.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_MONMIN(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Operand op;
+ int reg;
+ int regHi;
+
+ inner = expr->data.monadic;
+ memclrw(&op, sizeof(Operand));
+ GEN_NODE(inner, &op);
+ coerce_to_register_pair(&op, inner->rtype, 0, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+ emitpcode(PC_SUBFIC, reg, op.reg, 0);
+ emitpcode(PC_SUBFZE, regHi, op.regHi);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_ASS(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *type;
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ VarInfo *vi;
+
+ type = expr->rtype;
+ if (ENODE_IS(expr, ECONDASS)) {
+ left = expr->data.cond.expr1;
+ if (ENODE_IS(left, EINDIRECT))
+ left = left->data.monadic;
+ else
+ CError_FATAL(8328);
+ right = expr->data.cond.expr2;
+ } else {
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ }
+
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ if (ENODE_IS(left, EOBJREF) && OBJECT_REG(left->data.objref)) {
+ vi = Registers_GetVarInfo(left->data.objref);
+ GEN_NODE_TO_REG(right, vi->reg, vi->regHi, &opright);
+ if (vi->rclass != RegClass_GPR) {
+ CError_FATAL(8348);
+ } else {
+ coerce_to_register_pair(&opright, type, vi->reg, vi->regHi);
+ *output = opright;
+ }
+ return;
+ }
+
+ if (TYPE_FITS_IN_REGISTER(type)) {
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ if (ENODE_IS(left, EBITFIELD)) {
+ CError_FATAL(8376);
+ } else {
+ GEN_NODE(left, &opleft);
+ indirect(&opleft, left);
+ store_pair(opright.reg, opright.regHi, &opleft, type);
+ }
+
+ output->optype = OpndType_GPRPair;
+ output->reg = opright.reg;
+ output->regHi = opright.regHi;
+ }
+}
+
+void I8_gen_POSTINCDEC(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ Type *type;
+ int flag;
+ int reg;
+ int regHi;
+ Operand op1;
+ Operand op2;
+ Operand op3;
+
+ inner = expr->data.monadic->data.monadic;
+ type = expr->rtype;
+ flag = 0;
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ if (ENODE_IS(inner, EOBJREF) && (reg = OBJECT_REG(inner->data.objref))) {
+ regHi = Registers_GetVarInfo(inner->data.objref)->regHi;
+ output->optype = OpndType_GPRPair;
+ output->reg = (outputReg && outputReg != reg && outputReg != regHi) ? outputReg : ALLOC_GPR();
+ output->regHi = (outputRegHi && outputRegHi != regHi && outputRegHi != reg) ? outputRegHi : ALLOC_GPR();
+ emitpcode(PC_MR, output->reg, reg);
+ emitpcode(PC_MR, output->regHi, regHi);
+ if (ENODE_IS(expr, EPOSTINC)) {
+ emitpcode(PC_ADDIC, reg, reg, 1);
+ emitpcode(PC_ADDME, regHi, regHi);
+ } else {
+ emitpcode(PC_ADDIC, reg, reg, -1);
+ emitpcode(PC_ADDZE, regHi, regHi);
+ }
+ return;
+ }
+
+ CError_ASSERT(8446, !ENODE_IS(inner, EBITFIELD));
+
+ GEN_NODE(inner, &op1);
+ indirect(&op1, inner);
+ op2 = op1;
+ coerce_to_register_pair(&op2, type, 0, 0);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = ALLOC_GPR();
+ output->regHi = ALLOC_GPR();
+
+ emitpcode(PC_MR, output->reg, op2.reg);
+ emitpcode(PC_MR, output->regHi, op2.regHi);
+
+ reg = ALLOC_GPR();
+ regHi = ALLOC_GPR();
+
+ if (ENODE_IS(expr, EPOSTINC)) {
+ emitpcode(PC_ADDIC, reg, op2.reg, 1);
+ emitpcode(PC_ADDZE, regHi, op2.regHi);
+ } else {
+ emitpcode(PC_ADDIC, reg, op2.reg, -1);
+ emitpcode(PC_ADDME, regHi, op2.regHi);
+ }
+ store_pair(reg, regHi, &op1, type);
+}
+
+void I8_gen_INDIRECT(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ ENode *inner;
+ VarInfo *vi;
+
+ inner = expr->data.monadic;
+ if (ENODE_IS(inner, EOBJREF) && OBJECT_REG(inner->data.objref)) {
+ vi = Registers_GetVarInfo(inner->data.objref);
+ switch (vi->rclass) {
+ case RegClass_GPR:
+ output->optype = OpndType_GPRPair;
+ break;
+ case RegClass_FPR:
+ output->optype = OpndType_FPR;
+ break;
+ default:
+ CError_FATAL(8511);
+ }
+
+ output->reg = vi->reg;
+ output->regHi = vi->regHi;
+ output->object = NULL;
+ return;
+ }
+
+ if (ENODE_IS(inner, EBITFIELD)) {
+ CError_FATAL(8529);
+ return;
+ }
+
+ GEN_NODE(inner, output);
+ indirect(output, inner);
+}
+
+void I8_gen_condition(ENode *cond, Operand *output, int write_to_gpr) {
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ Operand tmpop;
+ int reg1;
+ int reg2;
+ int reg3;
+ int reg4;
+ int reg5;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+ memclrw(&tmpop, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &opright);
+ if (right->rtype->size < 4)
+ extend32(&opright, right->rtype, 0);
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ if (right->rtype->size < 8) {
+ short tmp = ALLOC_GPR();
+ if (is_unsigned(right->rtype))
+ load_immediate(tmp, 0);
+ else
+ emitpcode(PC_SRAWI, tmp, opright.reg, 31);
+ opright.optype = OpndType_GPRPair;
+ opright.regHi = tmp;
+ }
+
+ GEN_NODE(left, &opleft);
+ if (left->rtype->size < 4)
+ extend32(&opleft, left->rtype, 0);
+ ENSURE_GPR(&opleft, left->rtype, 0);
+
+ if (left->rtype->size < 8) {
+ short tmp = ALLOC_GPR();
+ // this looks like a bug??? surely this should check left->rtype
+ if (is_unsigned(right->rtype))
+ load_immediate(tmp, 0);
+ else
+ emitpcode(PC_SRAWI, tmp, opleft.reg, 31);
+ opleft.optype = OpndType_GPRPair;
+ opleft.regHi = tmp;
+ }
+ } else {
+ GEN_NODE(left, &opleft);
+ ENSURE_GPR(&opleft, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&opleft, left->rtype, 0);
+
+ if (left->rtype->size < 8) {
+ short tmp = ALLOC_GPR();
+ if (is_unsigned(right->rtype))
+ load_immediate(tmp, 0);
+ else
+ emitpcode(PC_SRAWI, tmp, opleft.reg, 31);
+ opleft.optype = OpndType_GPRPair;
+ opleft.regHi = tmp;
+ }
+
+ GEN_NODE(right, &opright);
+ if (right->rtype->size < 4)
+ extend32(&opright, right->rtype, 0);
+ ENSURE_GPR(&opright, right->rtype, 0);
+
+ if (right->rtype->size < 8) {
+ short tmp = ALLOC_GPR();
+ if (is_unsigned(right->rtype))
+ load_immediate(tmp, 0);
+ else
+ emitpcode(PC_SRAWI, tmp, opright.reg, 31);
+ opright.optype = OpndType_GPRPair;
+ opright.regHi = tmp;
+ }
+ }
+
+ CError_ASSERT(8704, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ switch (cond->type) {
+ case EEQU:
+ case ENOTEQU:
+ reg1 = ALLOC_GPR();
+ reg2 = ALLOC_GPR();
+ emitpcode(PC_XOR, reg1, opleft.reg, opright.reg);
+ emitpcode(PC_XOR, reg2, opleft.regHi, opright.regHi);
+ emitpcode(PC_OR, reg2, reg1, reg2);
+ if (write_to_gpr) {
+ if (ENODE_IS(cond, EEQU)) {
+ emitpcode(PC_CNTLZW, reg2, reg2);
+ emitpcode(PC_RLWINM, reg2, reg2, 27, 5, 31);
+ } else {
+ emitpcode(PC_ADDIC, reg1, reg2, -1);
+ emitpcode(PC_SUBFE, reg2, reg1, reg2);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg2;
+ output->regHi = 0;
+ } else {
+ emitpcode(PC_CMPI, 0, reg2, 0);
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = cond->type;
+ }
+ break;
+ case EGREATER:
+ tmpop = opleft;
+ opleft = opright;
+ opright = tmpop;
+ case ELESS:
+ reg1 = ALLOC_GPR();
+ reg2 = ALLOC_GPR();
+ reg3 = ALLOC_GPR();
+ if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) {
+ emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000);
+ emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000);
+ reg4 = reg1;
+ reg5 = reg2;
+ } else {
+ reg4 = opleft.regHi;
+ reg5 = opright.regHi;
+ }
+ emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg);
+ emitpcode(PC_SUBFE, reg2, reg5, reg4);
+ emitpcode(PC_SUBFE, reg2, reg1, reg1);
+ emitpcode(PC_NEG, reg2, reg2);
+ if (write_to_gpr) {
+ output->optype = OpndType_GPR;
+ output->reg = reg2;
+ output->regHi = 0;
+ } else {
+ emitpcode(PC_CMPI, 0, reg2, 0);
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = ENOTEQU;
+ }
+ break;
+ case ELESSEQU:
+ tmpop = opleft;
+ opleft = opright;
+ opright = tmpop;
+ case EGREATEREQU:
+ reg1 = ALLOC_GPR();
+ reg2 = ALLOC_GPR();
+ reg3 = ALLOC_GPR();
+ if (left->rtype != TYPE(&stunsignedlonglong) && right->rtype != TYPE(&stunsignedlonglong)) {
+ emitpcode(PC_XORIS, reg1, opleft.regHi, 0x8000);
+ emitpcode(PC_XORIS, reg2, opright.regHi, 0x8000);
+ reg4 = reg1;
+ reg5 = reg2;
+ } else {
+ reg4 = opleft.regHi;
+ reg5 = opright.regHi;
+ }
+ emitpcode(PC_SUBFC, reg3, opright.reg, opleft.reg);
+ emitpcode(PC_SUBFE, reg2, reg5, reg4);
+ emitpcode(PC_SUBFE, reg2, reg1, reg1);
+ emitpcode(PC_NEG, reg2, reg2);
+ if (write_to_gpr) {
+ emitpcode(PC_SUBFIC, reg2, reg2, 1);
+ output->optype = OpndType_GPR;
+ output->reg = reg2;
+ output->regHi = 0;
+ } else {
+ emitpcode(PC_CMPI, 0, reg2, 0);
+ output->optype = OpndType_CRField;
+ output->reg = 0;
+ output->regOffset = EEQU;
+ }
+ break;
+ default:
+ CError_FATAL(8814);
+ }
+}
+
+void I8_gen_SHL_SHR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5)};
+
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ int is_uns;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = ALLOC_GPR();
+ output->regHi = ALLOC_GPR();
+
+ is_uns = is_unsigned(expr->rtype) != 0;
+
+ if (ENODE_IS(right, EINTCONST)) {
+ if (ENODE_IS(expr, ESHL)) {
+ I8_ShiftLeftImmediate(opleft, right->data.intval.lo, is_uns, expr->rtype->size, output->reg, output->regHi);
+ } else {
+ I8_ShiftRightImmediate(opleft, right->data.intval.lo, is_uns, output->reg, output->regHi, 0);
+ }
+ return;
+ }
+
+ GEN_NODE(right, &opright);
+ ENSURE_GPR(&opright, right->rtype, 0);
+ if (opright.optype == OpndType_GPRPair) {
+ opright.regHi = 0;
+ opright.optype = OpndType_GPR;
+ }
+
+ CError_ASSERT(8890, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPR);
+
+ if (opleft.regHi != high_reg)
+ emitpcode(PC_MR, high_reg, opleft.regHi);
+ if (opleft.reg != low_reg)
+ emitpcode(PC_MR, low_reg, opleft.reg);
+ if (opright.reg != 5)
+ emitpcode(PC_MR, 5, opright.reg);
+
+ if (ENODE_IS(expr, ESHR)) {
+ if (is_unsigned(left->rtype))
+ branch_subroutine(rt_shr2u, 0, used_regs);
+ else
+ branch_subroutine(rt_shr2i, 0, used_regs);
+ } else if (ENODE_IS(expr, ESHL)) {
+ branch_subroutine(rt_shl2i, 0, used_regs);
+ } else {
+ CError_FATAL(8909);
+ }
+
+ emitpcode(PC_MR, output->reg, low_reg);
+ emitpcode(PC_MR, output->regHi, high_reg);
+}
+
+void I8_gen_DIV_MOD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)};
+
+ int is_uns;
+ ENode *left;
+ ENode *right;
+ Operand opleft;
+ Operand opright;
+ SInt64 constval;
+ int shift;
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ memclrw(&opleft, sizeof(Operand));
+ memclrw(&opright, sizeof(Operand));
+
+ GEN_NODE(left, &opleft);
+ coerce_to_register_pair(&opleft, left->rtype, 0, 0);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = ALLOC_GPR();
+ output->regHi = ALLOC_GPR();
+
+ is_uns = is_unsigned(expr->rtype) != 0;
+
+ if (ENODE_IS(right, EINTCONST))
+ constval = (((SInt64) right->data.intval.hi) << 32) + right->data.intval.lo;
+ if (ENODE_IS(right, EINTCONST) && ((shift = I8_log2n(constval)) > 0)) {
+ CError_ASSERT(8976, opleft.optype == OpndType_GPRPair);
+ if (ENODE_IS(expr, EDIV)) {
+ I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1);
+ if (!is_uns) {
+ emitpcode(PC_ADDZE, output->reg, output->reg);
+ emitpcode(PC_ADDZE, output->regHi, output->regHi);
+ }
+ } else {
+ if (is_uns) {
+ if (shift < 32) {
+ emitpcode(PC_LI, output->regHi, 0);
+ emitpcode(PC_RLWINM, output->reg, opleft.reg, 0, 32 - shift, 31);
+ } else if (shift == 32) {
+ emitpcode(PC_LI, output->regHi, 0);
+ emitpcode(PC_MR, output->reg, opleft.reg);
+ } else if (shift <= 63) {
+ emitpcode(PC_RLWINM, output->regHi, opleft.regHi, 0, 32 - (shift - 32), 31);
+ emitpcode(PC_MR, output->reg, opleft.reg);
+ } else {
+ CError_FATAL(9018);
+ }
+ } else {
+ short tmpreg1 = ALLOC_GPR();
+ short tmpreg2 = ALLOC_GPR();
+ I8_ShiftRightImmediate(opleft, shift, is_uns, output->reg, output->regHi, 1);
+ emitpcode(PC_ADDZE, output->reg, output->reg);
+ emitpcode(PC_ADDZE, output->regHi, output->regHi);
+ I8_ShiftLeftImmediate(*output, shift, is_uns, expr->rtype->size, tmpreg1, tmpreg2);
+ emitpcode(PC_SUBFC, output->reg, tmpreg1, opleft.reg);
+ emitpcode(PC_SUBFE, output->regHi, tmpreg2, opleft.regHi);
+ }
+ }
+ return;
+ }
+
+ GEN_NODE(right, &opright);
+ coerce_to_register_pair(&opright, right->rtype, 0, 0);
+
+ CError_ASSERT(9048, opleft.optype == OpndType_GPRPair && opright.optype == OpndType_GPRPair);
+
+ if (opleft.regHi != high_reg)
+ emitpcode(PC_MR, high_reg, opleft.regHi);
+ if (opleft.reg != low_reg)
+ emitpcode(PC_MR, low_reg, opleft.reg);
+ if (opright.regHi != high_reg2)
+ emitpcode(PC_MR, high_reg2, opright.regHi);
+ if (opright.reg != low_reg2)
+ emitpcode(PC_MR, low_reg2, opright.reg);
+
+ if (ENODE_IS(expr, EDIV)) {
+ if (is_unsigned(left->rtype) || is_unsigned(right->rtype))
+ branch_subroutine(rt_div2u, 0, used_regs);
+ else
+ branch_subroutine(rt_div2i, 0, used_regs);
+ } else if (ENODE_IS(expr, EMODULO)) {
+ if (is_unsigned(left->rtype) || is_unsigned(right->rtype))
+ branch_subroutine(rt_mod2u, 0, used_regs);
+ else
+ branch_subroutine(rt_mod2i, 0, used_regs);
+ } else {
+ CError_FATAL(9074);
+ }
+
+ emitpcode(PC_MR, output->reg, low_reg);
+ emitpcode(PC_MR, output->regHi, high_reg);
+}
+
+void I8_gen_TYPCON(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ Type *dsttype;
+ ENode *inner;
+ Type *srctype;
+ short regHi;
+ short reg;
+
+ static UInt32 used_regs[RegClassMax] = {0, 0, 0, 0, (1 << 3) | (1 << 4)};
+ static UInt32 used_regs_f1[RegClassMax] = {0, 0, 0, (1 << 1), 0};
+
+ inner = expr->data.monadic;
+ srctype = inner->rtype;
+ dsttype = expr->rtype;
+
+ if (IS_TYPE_VOID(dsttype)) {
+ GEN_NODE(inner, output);
+ if (ENODE_IS(inner, EINDIRECT) && (output->flags & OpndFlags_Volatile))
+ coerce_to_register_pair(output, inner->rtype, 0, 0);
+ output->optype = OpndType_Absolute;
+ output->immediate = 0;
+ return;
+ }
+
+ if (IS_TYPE_INT_OR_ENUM(srctype)) {
+ if (IS_TYPE_FLOAT(dsttype)) {
+ GEN_NODE(inner, output);
+ coerce_to_register_pair(output, srctype, 0, 0);
+ if (output->regHi != high_reg)
+ emitpcode(PC_MR, high_reg, output->regHi);
+ if (output->reg != low_reg)
+ emitpcode(PC_MR, low_reg, output->reg);
+
+ if (is_unsigned(srctype)) {
+ branch_subroutine(
+ (dsttype->size == 4) ? rt_cvt_ull_flt : rt_cvt_ull_dbl,
+ 0,
+ used_regs);
+ } else {
+ branch_subroutine(
+ (dsttype->size == 4) ? rt_cvt_sll_flt : rt_cvt_sll_dbl,
+ 0,
+ used_regs);
+ }
+
+ output->optype = OpndType_FPR;
+ output->reg = ALLOC_FPR();
+ emitpcode(PC_FMR, output->reg, 1);
+ return;
+ }
+
+ if (srctype->size < dsttype->size) {
+ CError_ASSERT(9171, TYPE_IS_8BYTES(dsttype));
+
+ GEN_NODE(inner, output);
+ if (srctype->size < 4 &&
+ !ENODE_IS_INDIRECT_TO(inner, EBITFIELD) &&
+ !((ENODE_IS_ASSIGN(inner) || ENODE_IS_RANGE(inner, EPOSTINC, EPREDEC)) && ENODE_IS(inner->data.monadic->data.monadic, EBITFIELD))
+ ) {
+ extend32(output, srctype, outputReg);
+ }
+ extend64(output, srctype, outputReg, outputRegHi);
+ } else {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ if (dsttype->size < srctype->size) {
+ coerce_to_register_pair(output, srctype, outputReg, outputRegHi);
+ output->optype = OpndType_GPR;
+ output->regHi = 0;
+ }
+ }
+ return;
+ }
+
+ if (IS_TYPE_POINTER(srctype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+ CError_ASSERT(9200, TYPE_IS_8BYTES(expr->rtype));
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+
+ regHi = outputRegHi ? outputRegHi : ALLOC_GPR();
+ if (regHi == output->reg) {
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_MR, reg, output->reg);
+ output->reg = reg;
+ }
+ if (is_unsigned(inner->rtype))
+ load_immediate(regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, output->reg, 31);
+ output->optype = OpndType_GPRPair;
+ output->regHi = regHi;
+ return;
+ }
+
+ if (IS_TYPE_FLOAT(srctype)) {
+ if (IS_TYPE_FLOAT(dsttype)) {
+ CError_FATAL(9222);
+ return;
+ }
+
+ GEN_NODE(inner, output);
+ ENSURE_FPR(output, srctype, 0);
+ if (output->reg != 1)
+ emitpcode(PC_FMR, 1, output->reg);
+
+ branch_subroutine(rt_cvt_dbl_usll, 0, used_regs_f1);
+
+ output->optype = OpndType_GPRPair;
+ output->reg = ALLOC_GPR();
+ output->regHi = ALLOC_GPR();
+ emitpcode(PC_MR, output->reg, low_reg);
+ emitpcode(PC_MR, output->regHi, high_reg);
+ return;
+ }
+
+ if (IS_TYPE_STRUCT(srctype)) {
+ GEN_NODE_TO_REG(inner, outputReg, 0, output);
+
+ if (TYPE_IS_8BYTES(expr->rtype) && dsttype->size == srctype->size) {
+ coerce_to_register_pair(output, srctype, outputReg, outputRegHi);
+ } else {
+ CError_FATAL(9256);
+ }
+ return;
+ }
+
+ CError_FATAL(9261);
+}
+
+void gen_VECTOR128CONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+ int gpr;
+ int vr;
+ COVCResult result;
+
+ vr = outputReg ? outputReg : ALLOC_VR();
+ if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, &result))
+ CError_FATAL(9282);
+
+ if (result.op1 != -1) {
+ emitpcode(result.op1, vr, result.arg);
+ output->optype = OpndType_VR;
+ output->reg = vr;
+ return;
+ }
+
+ if (result.op2 != -1) {
+ gpr = ALLOC_GPR();
+ emitpcode(PC_LI, gpr, result.arg);
+ emitpcode(result.op2, vr, 0, gpr);
+ output->optype = OpndType_VR;
+ output->reg = vr;
+ return;
+ }
+
+ CError_FATAL(9298);
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c
new file mode 100644
index 0000000..49334b8
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Intrinsics.c
@@ -0,0 +1,4894 @@
+#include "compiler/Intrinsics.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CScope.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/FunctionCalls.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/PPCError.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/StructMoves.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/types.h"
+
+Object *__memcpy_object;
+static Object *intrinsics[311];
+int VectorConditions; // unused?
+static Object *cur_intrinsic_object;
+
+static TypePointer stvectorunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedchar), 0};
+static TypePointer stvectorsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedchar), 0};
+static TypePointer stvectorboolchar_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolchar), 0};
+static TypePointer stvectorunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedshort), 0};
+static TypePointer stvectorsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedshort), 0};
+static TypePointer stvectorboolshort_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboolshort), 0};
+static TypePointer stvectorunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorunsignedlong), 0};
+static TypePointer stvectorsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorsignedlong), 0};
+static TypePointer stvectorboollong_ptr = {TYPEPOINTER, 4, TYPE(&stvectorboollong), 0};
+static TypePointer stvectorfloat_ptr = {TYPEPOINTER, 4, TYPE(&stvectorfloat), 0};
+static TypePointer stvectorpixel_ptr = {TYPEPOINTER, 4, TYPE(&stvectorpixel), 0};
+static TypePointer stunsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedchar), 0};
+static TypePointer stsignedchar_ptr = {TYPEPOINTER, 4, TYPE(&stsignedchar), 0};
+static TypePointer stunsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedshort), 0};
+static TypePointer stsignedshort_ptr = {TYPEPOINTER, 4, TYPE(&stsignedshort), 0};
+static TypePointer stunsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedlong), 0};
+static TypePointer stsignedlong_ptr = {TYPEPOINTER, 4, TYPE(&stsignedlong), 0};
+static TypePointer stunsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stunsignedint), 0};
+static TypePointer stsignedint_ptr = {TYPEPOINTER, 4, TYPE(&stsignedint), 0};
+static TypePointer stfloat_ptr = {TYPEPOINTER, 4, TYPE(&stfloat), 0};
+
+// Verify1VectorArg2Ops
+typedef struct TypeTable22 {
+ Type *rtype;
+ Type *arg1;
+ int opcode1;
+ int opcode2;
+} TypeTable22;
+
+// VerifyNoVectorArgs
+typedef struct TypeTable11 {
+ Type *rtype;
+ int opcode;
+} TypeTable11;
+
+// Verify1VectorArg
+typedef struct TypeTable21 {
+ Type *rtype;
+ Type *arg1;
+ int opcode;
+} TypeTable21;
+
+// Verify2VectorArgs
+typedef struct TypeTable31 {
+ Type *rtype;
+ Type *arg1;
+ Type *arg2;
+ int opcode;
+} TypeTable31;
+
+// Verify3VectorArgs
+typedef struct TypeTable41 {
+ Type *rtype;
+ Type *arg1;
+ Type *arg2;
+ Type *arg3;
+ int opcode;
+} TypeTable41;
+
+static TypeTable31 vector_add_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_addc_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDCUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_adds_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_and_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAND,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VAND,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VAND,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAND,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VAND,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VAND,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VAND,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAND,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VAND,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VAND,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAND,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VAND,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VAND,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VAND,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAND,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VAND,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VAND,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAND,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VAND,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VAND,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VAND,
+ TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VAND,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VAND,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VAND,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_andc_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VANDC,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VANDC,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VANDC,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VANDC,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VANDC,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VANDC,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VANDC,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VANDC,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VANDC,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VANDC,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VANDC,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VANDC,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VANDC,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VANDC,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VANDC,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VANDC,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VANDC,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VANDC,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VANDC,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VANDC,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VANDC,
+ TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VANDC,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VANDC,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_avg_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_ceil_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_cmpb_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_cmpeq_type_table[] = {
+ TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_cmpge_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_cmpgt_type_table[] = {
+ TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_ctf_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX,
+ TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_cts_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTSXS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_ctu_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VCTUXS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_dss_type_table[] = {
+ TYPE(&stvoid), TYPE(&stsignedint), PC_DSS, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable11 vector_dssall_type_table[] = {
+ TYPE(&stvoid), PC_DSSALL,
+ NULL, 0
+};
+static TypeTable41 vector_datastream_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorboolchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorboolshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorpixel_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorboollong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stvectorfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stunsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stsignedchar_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stunsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stsignedshort_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stunsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stsignedint_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stunsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stsignedlong_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ TYPE(&stvoid), TYPE(&stfloat_ptr), TYPE(&stsignedint), TYPE(&stsignedint), PC_DST,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_expte_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VEXPTEFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_floor_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIM, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_load_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVX,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVX,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVX,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVX,
+ TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVX,
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVX,
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVX,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVX,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVX,
+ TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVX,
+ TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVX,
+ TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVX,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVX,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_loade_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX,
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_loadl_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVXL,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_LVXL,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVXL,
+ TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVXL,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_LVXL,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVXL,
+ TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_LVXL,
+ TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVXL,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVXL,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_LVXL,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVXL,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVXL,
+ TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_LVXL,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_LVXL,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVXL,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_loge_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VLOGEFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_lvsl_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSL,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_lvsr_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVSR,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_madd_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMADDFP,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_madds_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHADDSHS,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_max_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_mergeh_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_mergel_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable11 vector_mfvscr_type_table[] = {
+ TYPE(&stvectorunsignedshort), PC_MFVSCR,
+ NULL, 0
+};
+static TypeTable31 vector_min_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_mladd_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMLADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMLADDUHM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_mradds_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMHRADDSHS,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_msum_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_msums_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable21 vector_mtvscr_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorpixel), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), PC_MTVSCR,
+ TYPE(&stvoid), TYPE(&stvectorboollong), PC_MTVSCR,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_mule_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_mulo_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_nmsub_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNMSUBFP,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_nor_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VNOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VNOR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VNOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VNOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VNOR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VNOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VNOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VNOR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VNOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VNOR,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_or_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VOR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VOR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VOR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VOR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VOR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VOR,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_pack_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_packpx_type_table[] = {
+ TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKPX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_packs_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_packsu_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_perm_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VPERM,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VPERM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_re_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VREFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_rl_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_round_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIN, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_rsqrte_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRSQRTEFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable41 vector_sel_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSEL,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSEL,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSEL,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSEL,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VSEL,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSEL,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSEL,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSEL,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSEL,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VSEL,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSEL,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSEL,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSEL,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSEL,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VSEL,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), PC_VSEL,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VSEL,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sl_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_sld_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSLDOI,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSLDOI,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sll_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSL,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSL,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSL,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSL,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_slo_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSLO,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSLO,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSLO,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_splat_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_splat_s8_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_splat_s16_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_splat_s32_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_splat_u8_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_splat_u16_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_splat_u32_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_sr_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sra_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_srl_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedchar), PC_VSR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedshort), PC_VSR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSR,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sro_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), PC_VSRO,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorunsignedchar), PC_VSRO,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorsignedchar), PC_VSRO,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_st_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVX,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_ste_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_stl_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stvectorunsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stvectorsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stvectorunsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stvectorsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stvectorunsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stvectorsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stvectorfloat_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stvectorpixel_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stvectorboolchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stvectorboolshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stvectorboollong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVXL,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVXL,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sub_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_subc_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBCUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_subs_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sum4s_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sum2s_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUM2SWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_sums_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUMSWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_trunc_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VRFIZ, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_unpack2sh_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_unpack2sl_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_unpack2uh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_unpack2ul_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable21 vector_unpackh_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH,
+ TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH,
+ NULL, NULL, 0
+};
+static TypeTable21 vector_unpackl_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH,
+ TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_xor_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VXOR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VXOR,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VXOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VXOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VXOR,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VXOR,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VXOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VXOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VXOR,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VXOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VXOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VXOR,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VXOR,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VXOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VXOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VXOR,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VXOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VXOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VXOR,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VXOR,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VXOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorboollong), TYPE(&stvectorfloat), PC_VXOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorboollong), PC_VXOR,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VXOR,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_eq_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_ge_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_gt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_in_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_le_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_lt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP
+};
+static TypeTable22 vector_all_nan_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_all_ne_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_nge_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_ngt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_nle_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_all_nlt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_all_numeric_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_any_eq_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_ge_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_gt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_le_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_lt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_any_nan_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_any_ne_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VCMPEQUB,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VCMPEQUH,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VCMPEQUW,
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_nge_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_ngt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_nle_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGEFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_any_nlt_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_any_numeric_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), PC_VCMPEQFP, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_any_out_type_table[] = {
+ TYPE(&stsignedint), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddubm_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDUBM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vadduhm_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDUHM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vadduwm_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDUWM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddfp_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VADDFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddubs_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VADDUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VADDUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VADDUBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddsbs_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VADDSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VADDSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VADDSBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vadduhs_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VADDUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VADDUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VADDUHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddshs_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VADDSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VADDSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VADDSHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vadduws_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VADDUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VADDUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VADDUWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vaddsws_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VADDSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VADDSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VADDSWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavgub_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VAVGUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavgsb_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VAVGSB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavguh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VAVGUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavgsh_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VAVGSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavguw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VAVGUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vavgsw_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VAVGSW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpequb_type_table[] = {
+ TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPEQUB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPEQUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpequh_type_table[] = {
+ TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPEQUH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPEQUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpequw_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPEQUW,
+ TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPEQUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpeqfp_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPEQFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtub_type_table[] = {
+ TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VCMPGTUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtsb_type_table[] = {
+ TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VCMPGTSB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtuh_type_table[] = {
+ TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VCMPGTUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtsh_type_table[] = {
+ TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VCMPGTSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtuw_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VCMPGTUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtsw_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VCMPGTSW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcmpgtfp_type_table[] = {
+ TYPE(&stvectorboollong), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VCMPGTFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcfux_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VCFUX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vcfsx_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VCFSX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_lvebx_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_LVEBX,
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_LVEBX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_lvehx_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_LVEHX,
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_LVEHX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_lvewx_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_LVEWX,
+ TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_LVEWX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_LVEWX,
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_LVEWX,
+ TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_LVEWX,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxub_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMAXUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMAXUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMAXUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxsb_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMAXSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMAXSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMAXSB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxuh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMAXUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMAXUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMAXUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxsh_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMAXSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMAXSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMAXSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxuw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMAXUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMAXUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMAXUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxsw_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMAXSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMAXSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMAXSW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmaxfp_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMAXFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrghb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGHB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGHB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGHB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrghh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGHH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGHH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGHH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGHH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrghw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGHW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGHW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGHW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGHW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrglb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMRGLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMRGLB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), PC_VMRGLB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrglh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMRGLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMRGLH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VMRGLH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stvectorpixel), PC_VMRGLH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmrglw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMRGLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMRGLW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VMRGLW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMRGLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminub_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMINUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VMINUB,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VMINUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminsb_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMINSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VMINSB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VMINSB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminuh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMINUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VMINUH,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VMINUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminsh_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMINSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VMINSH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VMINSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminuw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VMINUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VMINUW,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VMINUW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminsw_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VMINSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VMINSW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VMINSW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vminfp_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VMINFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsumubm_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VMSUMUBM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsumuhm_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsummbm_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedlong), PC_VMSUMMBM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsumshm_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHM,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsumuhs_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), PC_VMSUMUHS,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_vmsumshs_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VMSUMSHS,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmuleub_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULEUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmulesb_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULESB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmuleuh_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULEUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmulesh_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULESH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmuloub_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VMULOUB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmulosb_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VMULOSB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmulouh_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VMULOUH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vmulosh_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VMULOSH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkuhum_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKUHUM,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), PC_VPKUHUM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkuwum_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKUWUM,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboollong), TYPE(&stvectorboollong), PC_VPKUWUM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkuhus_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VPKUHUS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkshss_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHSS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkuwus_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VPKUWUS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkswss_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWSS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkshus_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VPKSHUS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vpkswus_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VPKSWUS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vrlb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VRLB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vrlh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VRLH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vrlw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VRLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vslb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSLB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vslh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSLH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vslw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSLW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vspltb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), PC_VSPLTB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTB,
+ TYPE(&stvectorboolchar), TYPE(&stvectorboolchar), TYPE(&stsignedint), PC_VSPLTB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsplth_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolshort), TYPE(&stsignedint), PC_VSPLTH,
+ TYPE(&stvectorpixel), TYPE(&stvectorpixel), TYPE(&stsignedint), PC_VSPLTH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vspltw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorboollong), TYPE(&stvectorboollong), TYPE(&stsignedint), PC_VSPLTW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stsignedint), PC_VSPLTW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable22 vector_vspltisb_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stsignedint), PC_VSPLTISB, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_vspltish_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stsignedint), PC_VSPLTISH, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_vspltisw_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stsignedint), PC_VSPLTISW, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable31 vector_vsrb_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsrh_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsrw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsrab_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorunsignedchar), PC_VSRAB,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsrah_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorunsignedshort), PC_VSRAH,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsraw_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorunsignedlong), PC_VSRAW,
+ NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_stvebx_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedchar), TYPE(&stsignedint), TYPE(&stunsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorsignedchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX,
+ TYPE(&stvoid), TYPE(&stvectorboolchar), TYPE(&stsignedint), TYPE(&stsignedchar_ptr), PC_STVEBX,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_stvehx_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedshort), TYPE(&stsignedint), TYPE(&stunsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorsignedshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorboolshort), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ TYPE(&stvoid), TYPE(&stvectorpixel), TYPE(&stsignedint), TYPE(&stsignedshort_ptr), PC_STVEHX,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable41 vector_stvewx_type_table[] = {
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorunsignedlong), TYPE(&stsignedint), TYPE(&stunsignedlong_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorsignedlong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorfloat), TYPE(&stsignedint), TYPE(&stfloat_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedint_ptr), PC_STVEWX,
+ TYPE(&stvoid), TYPE(&stvectorboollong), TYPE(&stsignedint), TYPE(&stsignedlong_ptr), PC_STVEWX,
+ NULL, NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsububm_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBM,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBUBM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubuhm_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHM,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBUHM,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubuwm_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBUWM,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBUWM,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubfp_type_table[] = {
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VSUBFP,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsububs_type_table[] = {
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), PC_VSUBUBS,
+ TYPE(&stvectorunsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorunsignedchar), PC_VSUBUBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubsbs_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), PC_VSUBSBS,
+ TYPE(&stvectorsignedchar), TYPE(&stvectorboolchar), TYPE(&stvectorsignedchar), PC_VSUBSBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubuhs_type_table[] = {
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), PC_VSUBUHS,
+ TYPE(&stvectorunsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorunsignedshort), PC_VSUBUHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubshs_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), PC_VSUBSHS,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorboolshort), TYPE(&stvectorsignedshort), PC_VSUBSHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubuws_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), PC_VSUBUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), PC_VSUBUWS,
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorunsignedlong), PC_VSUBUWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsubsws_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), PC_VSUBSWS,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorboollong), TYPE(&stvectorsignedlong), PC_VSUBSWS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsum4ubs_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorunsignedchar), TYPE(&stvectorunsignedlong), PC_VSUM4UBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsum4sbs_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedchar), TYPE(&stvectorsignedlong), PC_VSUM4SBS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable31 vector_vsum4shs_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), TYPE(&stvectorsignedlong), PC_VSUM4SHS,
+ NULL, NULL, NULL, 0
+};
+static TypeTable21 vector_vupkhsb_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKHSB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKHSB,
+ NULL, NULL, 0
+};
+static TypeTable21 vector_vupklsb_type_table[] = {
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedchar), PC_VUPKLSB,
+ TYPE(&stvectorboolshort), TYPE(&stvectorboolchar), PC_VUPKLSB,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_vupkhpx_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKHPX, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_vupklpx_type_table[] = {
+ TYPE(&stvectorunsignedlong), TYPE(&stvectorpixel), PC_VUPKLPX, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable21 vector_vupkhsh_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKHSH,
+ TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKHSH,
+ NULL, NULL, 0
+};
+static TypeTable21 vector_vupklsh_type_table[] = {
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedshort), PC_VUPKLSH,
+ TYPE(&stvectorboollong), TYPE(&stvectorboolshort), PC_VUPKLSH,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_abs_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBUBM, PC_VMAXSB,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBUHM, PC_VMAXSH,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBUWM, PC_VMAXSW,
+ TYPE(&stvectorfloat), TYPE(&stvectorfloat), PC_VANDC, PC_B,
+ NULL, NULL, 0
+};
+static TypeTable22 vector_abss_type_table[] = {
+ TYPE(&stvectorsignedchar), TYPE(&stvectorsignedchar), PC_VSUBSBS, PC_VMAXSB,
+ TYPE(&stvectorsignedshort), TYPE(&stvectorsignedshort), PC_VSUBSHS, PC_VMAXSH,
+ TYPE(&stvectorsignedlong), TYPE(&stvectorsignedlong), PC_VSUBSWS, PC_VMAXSW,
+ NULL, NULL, 0
+};
+static void *typeTable[] = {
+ vector_add_type_table,
+ vector_addc_type_table,
+ vector_adds_type_table,
+ vector_and_type_table,
+ vector_andc_type_table,
+ vector_avg_type_table,
+ vector_ceil_type_table,
+ vector_cmpb_type_table,
+ vector_cmpeq_type_table,
+ vector_cmpge_type_table,
+ vector_cmpge_type_table,
+ vector_cmpgt_type_table,
+ vector_cmpgt_type_table,
+ vector_ctf_type_table,
+ vector_cts_type_table,
+ vector_ctu_type_table,
+ vector_dss_type_table,
+ vector_dssall_type_table,
+ vector_datastream_type_table,
+ vector_datastream_type_table,
+ vector_datastream_type_table,
+ vector_datastream_type_table,
+ vector_expte_type_table,
+ vector_floor_type_table,
+ vector_load_type_table,
+ vector_loade_type_table,
+ vector_loadl_type_table,
+ vector_loge_type_table,
+ vector_lvsl_type_table,
+ vector_lvsr_type_table,
+ vector_madd_type_table,
+ vector_madds_type_table,
+ vector_max_type_table,
+ vector_mergeh_type_table,
+ vector_mergel_type_table,
+ vector_mfvscr_type_table,
+ vector_min_type_table,
+ vector_mladd_type_table,
+ vector_mradds_type_table,
+ vector_msum_type_table,
+ vector_msums_type_table,
+ vector_mtvscr_type_table,
+ vector_mule_type_table,
+ vector_mulo_type_table,
+ vector_nmsub_type_table,
+ vector_nor_type_table,
+ vector_or_type_table,
+ vector_pack_type_table,
+ vector_packpx_type_table,
+ vector_packs_type_table,
+ vector_packsu_type_table,
+ vector_perm_type_table,
+ vector_re_type_table,
+ vector_rl_type_table,
+ vector_round_type_table,
+ vector_rsqrte_type_table,
+ vector_sel_type_table,
+ vector_sl_type_table,
+ vector_sld_type_table,
+ vector_sll_type_table,
+ vector_slo_type_table,
+ vector_splat_type_table,
+ vector_splat_s8_type_table,
+ vector_splat_s16_type_table,
+ vector_splat_s32_type_table,
+ vector_splat_u8_type_table,
+ vector_splat_u16_type_table,
+ vector_splat_u32_type_table,
+ vector_sr_type_table,
+ vector_sra_type_table,
+ vector_srl_type_table,
+ vector_sro_type_table,
+ vector_st_type_table,
+ vector_ste_type_table,
+ vector_stl_type_table,
+ vector_sub_type_table,
+ vector_subc_type_table,
+ vector_subs_type_table,
+ vector_sum4s_type_table,
+ vector_sum2s_type_table,
+ vector_sums_type_table,
+ vector_trunc_type_table,
+ vector_unpack2sh_type_table,
+ vector_unpack2sl_type_table,
+ vector_unpack2uh_type_table,
+ vector_unpack2ul_type_table,
+ vector_unpackh_type_table,
+ vector_unpackl_type_table,
+ vector_xor_type_table,
+ vector_all_eq_type_table,
+ vector_all_ge_type_table,
+ vector_all_gt_type_table,
+ vector_all_in_type_table,
+ vector_all_le_type_table,
+ vector_all_lt_type_table,
+ vector_all_nan_type_table,
+ vector_all_ne_type_table,
+ vector_all_nge_type_table,
+ vector_all_ngt_type_table,
+ vector_all_nle_type_table,
+ vector_all_nlt_type_table,
+ vector_all_numeric_type_table,
+ vector_any_eq_type_table,
+ vector_any_ge_type_table,
+ vector_any_gt_type_table,
+ vector_any_le_type_table,
+ vector_any_lt_type_table,
+ vector_any_nan_type_table,
+ vector_any_ne_type_table,
+ vector_any_nge_type_table,
+ vector_any_ngt_type_table,
+ vector_any_nle_type_table,
+ vector_any_nlt_type_table,
+ vector_any_numeric_type_table,
+ vector_any_out_type_table,
+ vector_vaddubm_type_table,
+ vector_vadduhm_type_table,
+ vector_vadduwm_type_table,
+ vector_vaddfp_type_table,
+ vector_addc_type_table,
+ vector_vaddubs_type_table,
+ vector_vaddsbs_type_table,
+ vector_vadduhs_type_table,
+ vector_vaddshs_type_table,
+ vector_vadduws_type_table,
+ vector_vaddsws_type_table,
+ vector_and_type_table,
+ vector_andc_type_table,
+ vector_vavgub_type_table,
+ vector_vavgsb_type_table,
+ vector_vavguh_type_table,
+ vector_vavgsh_type_table,
+ vector_vavguw_type_table,
+ vector_vavgsw_type_table,
+ vector_ceil_type_table,
+ vector_cmpb_type_table,
+ vector_vcmpequb_type_table,
+ vector_vcmpequh_type_table,
+ vector_vcmpequw_type_table,
+ vector_vcmpeqfp_type_table,
+ vector_cmpge_type_table,
+ vector_vcmpgtub_type_table,
+ vector_vcmpgtsb_type_table,
+ vector_vcmpgtuh_type_table,
+ vector_vcmpgtsh_type_table,
+ vector_vcmpgtuw_type_table,
+ vector_vcmpgtsw_type_table,
+ vector_vcmpgtfp_type_table,
+ vector_vcfux_type_table,
+ vector_vcfsx_type_table,
+ vector_cts_type_table,
+ vector_ctu_type_table,
+ vector_expte_type_table,
+ vector_floor_type_table,
+ vector_load_type_table,
+ vector_lvebx_type_table,
+ vector_lvehx_type_table,
+ vector_lvewx_type_table,
+ vector_loadl_type_table,
+ vector_loge_type_table,
+ vector_madd_type_table,
+ vector_madds_type_table,
+ vector_vmaxub_type_table,
+ vector_vmaxsb_type_table,
+ vector_vmaxuh_type_table,
+ vector_vmaxsh_type_table,
+ vector_vmaxuw_type_table,
+ vector_vmaxsw_type_table,
+ vector_vmaxfp_type_table,
+ vector_vmrghb_type_table,
+ vector_vmrghh_type_table,
+ vector_vmrghw_type_table,
+ vector_vmrglb_type_table,
+ vector_vmrglh_type_table,
+ vector_vmrglw_type_table,
+ vector_vminub_type_table,
+ vector_vminsb_type_table,
+ vector_vminuh_type_table,
+ vector_vminsh_type_table,
+ vector_vminuw_type_table,
+ vector_vminsw_type_table,
+ vector_vminfp_type_table,
+ vector_mladd_type_table,
+ vector_mradds_type_table,
+ vector_vmsumubm_type_table,
+ vector_vmsumuhm_type_table,
+ vector_vmsummbm_type_table,
+ vector_vmsumshm_type_table,
+ vector_vmsumuhs_type_table,
+ vector_vmsumshs_type_table,
+ vector_vmuleub_type_table,
+ vector_vmulesb_type_table,
+ vector_vmuleuh_type_table,
+ vector_vmulesh_type_table,
+ vector_vmuloub_type_table,
+ vector_vmulosb_type_table,
+ vector_vmulouh_type_table,
+ vector_vmulosh_type_table,
+ vector_nmsub_type_table,
+ vector_nor_type_table,
+ vector_or_type_table,
+ vector_vpkuhum_type_table,
+ vector_vpkuwum_type_table,
+ vector_packpx_type_table,
+ vector_vpkuhus_type_table,
+ vector_vpkshss_type_table,
+ vector_vpkuwus_type_table,
+ vector_vpkswss_type_table,
+ vector_vpkshus_type_table,
+ vector_vpkswus_type_table,
+ vector_perm_type_table,
+ vector_re_type_table,
+ vector_vrlb_type_table,
+ vector_vrlh_type_table,
+ vector_vrlw_type_table,
+ vector_round_type_table,
+ vector_rsqrte_type_table,
+ vector_sel_type_table,
+ vector_vslb_type_table,
+ vector_vslh_type_table,
+ vector_vslw_type_table,
+ vector_sld_type_table,
+ vector_sll_type_table,
+ vector_slo_type_table,
+ vector_vspltb_type_table,
+ vector_vsplth_type_table,
+ vector_vspltw_type_table,
+ vector_vspltisb_type_table,
+ vector_vspltish_type_table,
+ vector_vspltisw_type_table,
+ vector_vsrb_type_table,
+ vector_vsrh_type_table,
+ vector_vsrw_type_table,
+ vector_vsrab_type_table,
+ vector_vsrah_type_table,
+ vector_vsraw_type_table,
+ vector_srl_type_table,
+ vector_sro_type_table,
+ vector_st_type_table,
+ vector_stvebx_type_table,
+ vector_stvehx_type_table,
+ vector_stvewx_type_table,
+ vector_stl_type_table,
+ vector_vsububm_type_table,
+ vector_vsubuhm_type_table,
+ vector_vsubuwm_type_table,
+ vector_vsubfp_type_table,
+ vector_subc_type_table,
+ vector_vsububs_type_table,
+ vector_vsubsbs_type_table,
+ vector_vsubuhs_type_table,
+ vector_vsubshs_type_table,
+ vector_vsubuws_type_table,
+ vector_vsubsws_type_table,
+ vector_vsum4ubs_type_table,
+ vector_vsum4sbs_type_table,
+ vector_vsum4shs_type_table,
+ vector_sum2s_type_table,
+ vector_sums_type_table,
+ vector_trunc_type_table,
+ vector_vupkhsb_type_table,
+ vector_vupklsb_type_table,
+ vector_vupkhpx_type_table,
+ vector_vupklpx_type_table,
+ vector_vupkhsh_type_table,
+ vector_vupklsh_type_table,
+ vector_xor_type_table,
+ vector_abs_type_table,
+ vector_abss_type_table,
+ NULL
+};
+
+int is_intrinsic_function_call(ENode *funccall) {
+ ENode *funcref = funccall->data.funccall.funcref;
+ return
+ ENODE_IS(funcref, EOBJREF) &&
+ funcref->data.objref->datatype == DFUNC &&
+ (TYPE_FUNC(funcref->data.objref->type)->flags & FUNC_INTRINSIC);
+}
+
+static void abs_intrinsic(ENode *expr, short outputReg, Operand *output) {
+ int reg1;
+ int reg2;
+ Operand op;
+
+ memclrw(&op, sizeof(op));
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+
+ reg1 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, reg1, op.reg, 31);
+
+ reg2 = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_XOR, reg2, reg1, op.reg);
+ emitpcode(PC_SUBF, reg2, reg1, reg2);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg2;
+}
+
+static void setflm_intrinsic(ENode *expr, short outputReg, Operand *output, int flag) {
+ int reg;
+ Operand op;
+
+ memclrw(&op, sizeof(op));
+ GEN_NODE_TO_FPR(expr, &op, expr->rtype, 0);
+
+ if (!flag) {
+ output->optype = OpndType_FPR;
+ reg = (outputReg && outputReg != op.reg) ? outputReg : ALLOC_FPR();
+ emitpcode(PC_MFFS, output->reg = reg);
+ }
+
+ emitpcode(PC_MTFSF, 255, op.reg);
+}
+
+static void alloca_intrinsic(ENode *expr, short outputReg, Operand *output) {
+ int reg;
+ Operand op;
+
+ memclrw(&op, sizeof(op));
+
+ if (ENODE_IS(expr, EINTCONST)) {
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ allocate_dynamic_stack_space(
+ 1, reg, ALLOC_GPR(), CInt64_GetULong(&expr->data.intval));
+ } else {
+ GEN_NODE_TO_GPR(expr, &op, expr->rtype, 0);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+
+ emitpcode(PC_NEG, reg, op.reg);
+ emitpcode(PC_RLWINM, reg, reg, 0, 0, get_alloca_alignment());
+ allocate_dynamic_stack_space(0, reg, ALLOC_GPR(), 0);
+ }
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void load_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, short outputReg, Operand *output) {
+ int reg;
+ Operand op1;
+ Operand op2;
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+
+ if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) {
+ GEN_NODE(expr1, &op1);
+ if (op1.optype == OpndType_GPR_Indexed) {
+ emitpcode(opcode, reg, op1.reg, op1.regOffset);
+ } else {
+ ENSURE_GPR(&op1, expr1->rtype, 0);
+ emitpcode(opcode, reg, 0, op1.reg);
+ }
+ } else {
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0);
+ emitpcode(opcode, reg, op1.reg, op2.reg);
+ }
+
+ setpcodeflags(fSideEffects | ((expr1->flags | expr2->flags | output->flags) & (fIsConst | fIsVolatile)));
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void store_bytereversed_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2, ENode *expr3) {
+ Operand op1;
+ Operand op2;
+ Operand op3;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ memclrw(&op3, sizeof(op3));
+
+ if (ENODE_IS(expr3, EINTCONST) && expr3->data.intval.lo == 0) {
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE(expr2, &op2);
+ if (op2.optype == OpndType_GPR_Indexed) {
+ emitpcode(opcode, op1.reg, op2.reg, op2.regOffset);
+ } else {
+ ENSURE_GPR(&op2, expr2->rtype, 0);
+ emitpcode(opcode, op1.reg, 0, op2.reg);
+ }
+ } else {
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0);
+ GEN_NODE_TO_GPR(expr3, &op3, expr3->rtype, 0);
+ emitpcode(opcode, op1.reg, op2.reg, op3.reg);
+ }
+
+ setpcodeflags(fSideEffects | ((op1.flags | op2.flags | op3.flags) & (fIsConst | fIsVolatile)));
+}
+
+static void data_cache_block_intrinsic(Opcode opcode, ENode *expr1, ENode *expr2) {
+ Operand op1;
+ Operand op2;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+
+ if (ENODE_IS(expr2, EINTCONST) && expr2->data.intval.lo == 0) {
+ GEN_NODE(expr1, &op1);
+ if (op1.optype == OpndType_GPR_Indexed) {
+ emitpcode(opcode, op1.reg, op1.regOffset);
+ } else {
+ ENSURE_GPR(&op1, expr1->rtype, 0);
+ emitpcode(opcode, 0, op1.reg);
+ }
+ } else {
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0);
+ emitpcode(opcode, op1.reg, op2.reg);
+ }
+}
+
+static void memcpy_intrinsic(ENode *destexpr, ENode *srcexpr, SInt32 size, Boolean ignored, Operand *output) {
+ UInt32 qual;
+ Operand destOp;
+ Operand srcOp;
+
+ qual = 0;
+
+ memclrw(&destOp, sizeof(destOp));
+ memclrw(&srcOp, sizeof(srcOp));
+
+ GEN_NODE(srcexpr, &srcOp);
+ indirect(&srcOp, srcexpr);
+
+ GEN_NODE(destexpr, output);
+ destOp = *output;
+ indirect(&destOp, destexpr);
+
+ if (destOp.object)
+ qual = destOp.object->qual;
+
+ move_block(&destOp, &srcOp, size, destexpr->rtype ? CMach_AllocationAlignment(destexpr->rtype, qual) : 1);
+}
+
+static SInt32 checkconstintarg(ENode *expr, char *name, SInt32 min, SInt32 max, int argnum) {
+ SInt32 value;
+
+ if (!ENODE_IS(expr, EINTCONST))
+ PPCError_ErrorTerm(PPCErrorStr210, name, 3, max, argnum);
+
+ value = CInt64_GetULong(&expr->data.intval);
+
+ if (value < min) {
+ PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, min);
+ return min;
+ }
+
+ if (value > max) {
+ PPCError_Warning(PPCErrorStr211, name, argnum, value, min, max, value & max);
+ value = value & max;
+ }
+
+ return value;
+}
+
+static void rlwimi_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, ENode *expr5, short outputReg, Operand *output) {
+ SInt32 arg3;
+ SInt32 arg4;
+ SInt32 arg5;
+ Operand op1;
+ Operand op2;
+ int reg;
+ char *name = "__rlwimi";
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+
+ arg3 = checkconstintarg(expr3, name, 0, 31, 3);
+ arg4 = checkconstintarg(expr4, name, 0, 31, 4);
+ arg5 = checkconstintarg(expr5, name, 0, 31, 5);
+
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+
+ GEN_NODE(expr2, &op2);
+ if (copts.optimizationlevel > 1) {
+ reg = ALLOC_GPR();
+ emitpcode(PC_MR, reg, op1.reg);
+ op1.reg = reg;
+ }
+ ENSURE_GPR(&op2, expr2->rtype, 0);
+
+ emitpcode(PC_RLWIMI, op1.reg, op2.reg, arg3, arg4, arg5);
+
+ output->optype = OpndType_GPR;
+ output->reg = op1.reg;
+}
+
+static void rlwinm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) {
+ char *name = "__rlwinm";
+ short reg;
+ short arg2;
+ short arg3;
+ short arg4;
+ Operand op1;
+
+ memclrw(&op1, sizeof(op1));
+ arg2 = checkconstintarg(expr2, name, 0, 31, 2);
+ arg3 = checkconstintarg(expr3, name, 0, 31, 3);
+ arg4 = checkconstintarg(expr4, name, 0, 31, 4);
+
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, op1.reg, arg2, arg3, arg4);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static void rlwnm_intrinsic(ENode *expr1, ENode *expr2, ENode *expr3, ENode *expr4, short outputReg, Operand *output) {
+ short reg;
+ short arg3;
+ short arg4;
+ char *name = "__rlwnm";
+ Operand op1;
+ Operand op2;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ arg3 = checkconstintarg(expr3, name, 0, 31, 3);
+ arg4 = checkconstintarg(expr4, name, 0, 31, 4);
+
+ GEN_NODE_TO_GPR(expr1, &op1, expr1->rtype, 0);
+ GEN_NODE_TO_GPR(expr2, &op2, expr2->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWNM, reg, op1.reg, op2.reg, arg3, arg4);
+
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+static Boolean promotable_types_are_equal(Type *a, Type *b) {
+ if (a == b)
+ return 1;
+
+ if (a == TYPE(&stsignedint)) {
+ if (
+ b == TYPE(&stunsignedint) ||
+ b == TYPE(&stsignedchar) ||
+ b == TYPE(&stunsignedchar) ||
+ b == TYPE(&stsignedshort) ||
+ b == TYPE(&stunsignedshort) ||
+ b == TYPE(&stsignedlong) ||
+ b == TYPE(&stunsignedlong) ||
+ b == TYPE(&stbool)
+ )
+ return 1;
+ }
+
+ return 0;
+}
+
+static int Intrinsics_VerifyParameterCount(int wantedCount, ENodeList *args, HashNameNode *name) {
+ ENodeList *scan;
+ int count;
+
+ for (scan = args, count = 0; scan; scan = scan->next)
+ count++;
+
+ if (count != wantedCount) {
+ PPCError_Error(PPCErrorStr103, name->name, count, wantedCount);
+ return 0;
+ }
+
+ return 1;
+}
+
+static ENode *Intrinsics_CreateIntrinsicFunc(Object *func, ENodeList *args, Type *rtype) {
+ TypeFunc *tfunc;
+ ENodeList *scan;
+ ENode *expr;
+
+ tfunc = TYPE_FUNC(func->type);
+ CError_ASSERT(3741, IS_TYPE_FUNC(tfunc));
+
+ for (scan = args; scan; scan = scan->next) {
+ if (IS_TYPE_ARRAY(scan->node->rtype))
+ scan->node = CExpr_PointerGeneration(scan->node);
+ }
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->rtype = rtype;
+ expr->ignored = 0;
+ expr->flags = tfunc->qual & ENODE_FLAG_QUALS;
+ expr->data.funccall.funcref = create_objectrefnode(func);
+ expr->data.funccall.args = args;
+ expr->data.funccall.functype = tfunc;
+ return CExpr_AdjustFunctionCall(expr);
+}
+
+static Type *Intrinsics_Verify1VectorArg2Ops(Intrinsics id, ENodeList *args, HashNameNode *name) {
+ ENode *arg1;
+ TypeTable22 *table;
+ Type *typeA;
+ Type *typeB;
+ Type *rtype;
+
+ arg1 = args->node;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB = arg1->rtype;
+ typeA = table->arg1;
+ if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) {
+ typeA = TPTR_TARGET(typeA);
+ typeB = TPTR_TARGET(typeB);
+ }
+ if (promotable_types_are_equal(typeA, typeB))
+ break;
+ }
+
+ rtype = table->rtype;
+ if (!rtype) {
+ PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0);
+ rtype = NULL;
+ }
+ return rtype;
+}
+
+static Type *Intrinsics_VerifyNoVectorArgs(Intrinsics id, HashNameNode *name) {
+ TypeTable11 *table = typeTable[id - Intrinsic_042];
+ return table->rtype;
+}
+
+static Type *Intrinsics_Verify1VectorArg(Intrinsics id, ENodeList *args, HashNameNode *name) {
+ ENode *arg1;
+ TypeTable21 *table;
+ Type *typeA;
+ Type *typeB;
+ Type *rtype;
+
+ arg1 = args->node;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB = arg1->rtype;
+ typeA = table->arg1;
+ if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) {
+ typeA = TPTR_TARGET(typeA);
+ typeB = TPTR_TARGET(typeB);
+ }
+ if (promotable_types_are_equal(typeA, typeB))
+ break;
+ }
+
+ switch (id) {
+ case Intrinsic_104:
+ case Intrinsic_105:
+ case Intrinsic_106:
+ case Intrinsic_107:
+ case Intrinsic_108:
+ case Intrinsic_109:
+ case Intrinsic_269:
+ case Intrinsic_270:
+ case Intrinsic_271:
+ if (ENODE_IS(arg1, EINTCONST)) {
+ SInt32 val = arg1->data.intval.lo;
+ if (val > 15 || val < -16) {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 5);
+ return NULL;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 5);
+ return NULL;
+ }
+ break;
+ case Intrinsic_058:
+ if (ENODE_IS(arg1, EINTCONST)) {
+ SInt32 val = arg1->data.intval.lo;
+ if (val > 3 || val < 0) {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 2);
+ return NULL;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 2);
+ return NULL;
+ }
+ break;
+ }
+
+ rtype = table->rtype;
+ if (!rtype) {
+ PPCError_Error(PPCErrorStr104, name->name, name->name, arg1->rtype, 0);
+ rtype = NULL;
+ }
+ return rtype;
+}
+
+static Type *Intrinsics_Verify2VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) {
+ ENode *arg1;
+ ENode *arg2;
+ TypeTable31 *table;
+ Type *typeB1;
+ Type *typeB2;
+ Type *typeA1;
+ Type *typeA2;
+
+ arg1 = args->node;
+ arg2 = args->next->node;
+ table = typeTable[id - Intrinsic_042];
+
+ switch (id) {
+ case Intrinsic_055:
+ case Intrinsic_056:
+ case Intrinsic_057:
+ case Intrinsic_103:
+ case Intrinsic_190:
+ case Intrinsic_191:
+ case Intrinsic_192:
+ case Intrinsic_193:
+ case Intrinsic_266:
+ case Intrinsic_267:
+ case Intrinsic_268:
+ if (ENODE_IS(arg2, EINTCONST)) {
+ if (arg2->data.intval.lo > 31 || arg2->data.intval.hi < 0) {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 5);
+ return NULL;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 5);
+ return NULL;
+ }
+ break;
+ }
+
+ for (; table->rtype; table++) {
+ typeB1 = arg1->rtype;
+ typeB2 = arg2->rtype;
+ typeA1 = table->arg1;
+ typeA2 = table->arg2;
+ if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) {
+ typeA1 = TPTR_TARGET(typeA1);
+ typeB1 = TPTR_TARGET(typeB1);
+ }
+ if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) {
+ typeA2 = TPTR_TARGET(typeA2);
+ typeB2 = TPTR_TARGET(typeB2);
+ }
+ if (promotable_types_are_equal(typeA1, typeB1) &&
+ promotable_types_are_equal(typeA2, typeB2))
+ break;
+ }
+
+ if (!table->rtype) {
+ PPCError_Error(PPCErrorStr105, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0);
+ return NULL;
+ }
+
+ switch (id) {
+ case Intrinsic_066:
+ case Intrinsic_067:
+ case Intrinsic_068:
+ if (arg2->flags & ENODE_FLAG_VOLATILE)
+ PPCError_Warning(PPCErrorStr178, name->name);
+ }
+
+ return table->rtype;
+}
+
+static Type *Intrinsics_Verify3VectorArgs(Intrinsics id, ENodeList *args, HashNameNode *name) {
+ ENode *arg1;
+ ENode *arg2;
+ ENode *arg3;
+ TypeTable41 *table;
+ Type *typeB1;
+ Type *typeB2;
+ Type *typeB3;
+ Type *typeA1;
+ Type *typeA2;
+ Type *typeA3;
+
+ arg1 = args->node;
+ arg2 = args->next->node;
+ arg3 = args->next->next->node;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB1 = arg1->rtype;
+ typeB2 = arg2->rtype;
+ typeB3 = arg3->rtype;
+ typeA1 = table->arg1;
+ typeA2 = table->arg2;
+ typeA3 = table->arg3;
+ if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) {
+ typeA1 = TPTR_TARGET(typeA1);
+ typeB1 = TPTR_TARGET(typeB1);
+ }
+ if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) {
+ typeA2 = TPTR_TARGET(typeA2);
+ typeB2 = TPTR_TARGET(typeB2);
+ }
+ if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) {
+ typeA3 = TPTR_TARGET(typeA3);
+ typeB3 = TPTR_TARGET(typeB3);
+ }
+ if (promotable_types_are_equal(typeA1, typeB1) &&
+ promotable_types_are_equal(typeA2, typeB2) &&
+ promotable_types_are_equal(typeA3, typeB3))
+ break;
+ }
+
+ switch (id) {
+ case Intrinsic_060:
+ case Intrinsic_061:
+ case Intrinsic_062:
+ case Intrinsic_063:
+ if (ENODE_IS(arg3, EINTCONST)) {
+ SInt32 val = arg3->data.intval.lo;
+ if (val > 3 || val < 0) {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 2);
+ return NULL;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 2);
+ return NULL;
+ }
+ break;
+ case Intrinsic_100:
+ case Intrinsic_263:
+ if (ENODE_IS(arg3, EINTCONST)) {
+ if (arg3->data.intval.lo > 15 || arg3->data.intval.hi < 0) {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 4);
+ return NULL;
+ }
+ } else {
+ PPCError_Error(PPCErrorStr108, name->name, name->name, 4);
+ return NULL;
+ }
+ break;
+ }
+
+ if (!table->rtype) {
+ PPCError_Error(PPCErrorStr106, name->name, name->name, arg1->rtype, 0, arg2->rtype, 0, arg3->rtype, 0);
+ return NULL;
+ }
+
+ switch (id) {
+ case Intrinsic_114:
+ case Intrinsic_115:
+ case Intrinsic_116:
+ if (arg3->flags & ENODE_FLAG_VOLATILE)
+ PPCError_Warning(PPCErrorStr178, name->name);
+ }
+
+ return table->rtype;
+}
+
+static Opcode Intrinsics_FindOpcodeNoArgs(Intrinsics id, ENode *funccall) {
+ TypeTable11 *table = typeTable[id - Intrinsic_042];
+ return table->opcode;
+}
+
+static Opcode Intrinsics_FindOpcode1Arg(Intrinsics id, ENode *funccall, ENode *arg1) {
+ TypeTable21 *table;
+ Type *typeA;
+ Type *typeB;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB = arg1->rtype;
+ typeA = table->arg1;
+ if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) {
+ typeA = TPTR_TARGET(typeA);
+ typeB = TPTR_TARGET(typeB);
+ }
+ if (promotable_types_are_equal(typeA, typeB))
+ break;
+ }
+
+ CError_ASSERT(4105, table->rtype);
+ return table->opcode;
+}
+
+static Opcode Intrinsics_FindOpcode2Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2) {
+ TypeTable31 *table;
+ Type *typeB1;
+ Type *typeB2;
+ Type *typeA1;
+ Type *typeA2;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB1 = arg1->rtype;
+ typeB2 = arg2->rtype;
+ typeA1 = table->arg1;
+ typeA2 = table->arg2;
+ if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) {
+ typeA1 = TPTR_TARGET(typeA1);
+ typeB1 = TPTR_TARGET(typeB1);
+ }
+ if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) {
+ typeA2 = TPTR_TARGET(typeA2);
+ typeB2 = TPTR_TARGET(typeB2);
+ }
+ if (promotable_types_are_equal(typeA1, typeB1) &&
+ promotable_types_are_equal(typeA2, typeB2))
+ break;
+ }
+
+ CError_ASSERT(4144, table->rtype);
+ return table->opcode;
+}
+
+static Opcode Intrinsics_FindOpcode3Args(Intrinsics id, ENode *funccall, ENode *arg1, ENode *arg2, ENode *arg3) {
+ TypeTable41 *table;
+ Type *typeB1;
+ Type *typeB2;
+ Type *typeB3;
+ Type *typeA1;
+ Type *typeA2;
+ Type *typeA3;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB1 = arg1->rtype;
+ typeB2 = arg2->rtype;
+ typeB3 = arg3->rtype;
+ typeA1 = table->arg1;
+ typeA2 = table->arg2;
+ typeA3 = table->arg3;
+ if (IS_TYPE_POINTER(typeA1) && IS_TYPE_POINTER(typeB1)) {
+ typeA1 = TPTR_TARGET(typeA1);
+ typeB1 = TPTR_TARGET(typeB1);
+ }
+ if (IS_TYPE_POINTER(typeA2) && IS_TYPE_POINTER(typeB2)) {
+ typeA2 = TPTR_TARGET(typeA2);
+ typeB2 = TPTR_TARGET(typeB2);
+ }
+ if (IS_TYPE_POINTER(typeA3) && IS_TYPE_POINTER(typeB3)) {
+ typeA3 = TPTR_TARGET(typeA3);
+ typeB3 = TPTR_TARGET(typeB3);
+ }
+ if (promotable_types_are_equal(typeA1, typeB1) &&
+ promotable_types_are_equal(typeA2, typeB2) &&
+ promotable_types_are_equal(typeA3, typeB3))
+ break;
+ }
+
+ CError_ASSERT(4191, table->rtype);
+ return table->opcode;
+}
+
+static void vector_intrinsic_no_args(Opcode opcode) {
+ emitpcode(opcode);
+}
+
+static void vector_intrinsic_mfvscr(short outputReg, Opcode opcode, Operand *output) {
+ short reg;
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_splats(ENode *arg1, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ CError_ASSERT(4253, ENODE_IS(arg1, EINTCONST));
+ GEN_NODE(arg1, &op1);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.immediate);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_splatu8(ENode *arg1, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ CError_ASSERT(4277, ENODE_IS(arg1, EINTCONST));
+ GEN_NODE(arg1, &op1);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.immediate);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_splatu16(ENode *arg1, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ CError_ASSERT(4301, ENODE_IS(arg1, EINTCONST));
+ GEN_NODE(arg1, &op1);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.immediate);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_splatu32(ENode *arg1, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ CError_ASSERT(4325, ENODE_IS(arg1, EINTCONST));
+ GEN_NODE(arg1, &op1);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.immediate);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_dss(ENode *arg1) {
+ Operand op1;
+
+ memclrw(&op1, sizeof(op1));
+ CError_ASSERT(4348, ENODE_IS(arg1, EINTCONST));
+ GEN_NODE(arg1, &op1);
+
+ emitpcode(PC_DSS, op1.immediate, 0);
+}
+
+static void vector_intrinsic_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg, op2.reg);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_2args1const(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ CError_ASSERT(4393, ENODE_IS(arg2, EINTCONST));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE(arg2, &op2);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg, op2.immediate);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_3args(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ Operand op3;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ memclrw(&op3, sizeof(op3));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0);
+ GEN_NODE_TO_VR(arg3, &op3, arg3->rtype, 0);
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg, op2.reg, op3.reg);
+
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_datastream(ENode *arg1, ENode *arg2, ENode *arg3, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ CError_ASSERT(4445, ENODE_IS(arg3, EINTCONST));
+ GEN_NODE_TO_GPR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE_TO_GPR(arg2, &op2, arg2->rtype, 0);
+
+ switch (opcode) {
+ case PC_DST:
+ case PC_DSTST:
+ emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo, 0);
+ break;
+ case PC_DSTT:
+ case PC_DSTSTT:
+ emitpcode(opcode, op1.reg, op2.reg, arg3->data.intval.lo);
+ break;
+ default:
+ CError_FATAL(4463);
+ }
+}
+
+static void vector_intrinsic_sld(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ CError_ASSERT(4479, ENODE_IS(arg3, EINTCONST));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0);
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg, op2.reg, arg3->data.intval.lo);
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_load(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ short reg;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+
+ GEN_NODE(arg1, &op1);
+ if (op1.optype == OpndType_Absolute && op1.immediate == 0) {
+ op1.optype = OpndType_GPR;
+ op1.reg = 0;
+ } else {
+ ENSURE_GPR(&op1, arg1->rtype, 0);
+ }
+
+ GEN_NODE(arg2, &op2);
+ if (op2.optype == OpndType_Absolute && op2.immediate == 0 && op1.reg != 0) {
+ op2 = op1;
+ op1.optype = OpndType_GPR;
+ op1.reg = 0;
+ } else {
+ ENSURE_GPR(&op2, arg2->rtype, 0);
+ }
+
+ reg = outputReg ? outputReg : ALLOC_VR();
+
+ emitpcode(opcode, reg, op1.reg, op2.reg);
+ output->optype = OpndType_VR;
+ output->reg = reg;
+}
+
+static void vector_intrinsic_store(ENode *arg1, ENode *arg2, ENode *arg3, short outputReg, Operand *output, Opcode opcode) {
+ Operand op1;
+ Operand op2;
+ Operand op3;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+ memclrw(&op3, sizeof(op3));
+
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+
+ GEN_NODE(arg2, &op2);
+ if (op2.optype == OpndType_Absolute && op2.immediate == 0) {
+ op2.optype = OpndType_GPR;
+ op2.reg = 0;
+ } else {
+ ENSURE_GPR(&op2, arg2->rtype, 0);
+ }
+
+ GEN_NODE(arg3, &op3);
+ if (op3.optype == OpndType_Absolute && op3.immediate == 0 && op2.reg != 0) {
+ op3 = op2;
+ op2.optype = OpndType_GPR;
+ op2.reg = 0;
+ } else {
+ ENSURE_GPR(&op3, arg3->rtype, 0);
+ }
+
+ emitpcode(opcode, op1.reg, op2.reg, op3.reg);
+ output->optype = OpndType_VR;
+ output->reg = op1.reg;
+}
+
+static void vector_intrinsic_abs(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) {
+ TypeTable22 *table;
+ Type *typeA;
+ Type *typeB;
+ short reg1;
+ short reg2;
+ short reg3;
+ Operand op1;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB = arg1->rtype;
+ typeA = table->arg1;
+ if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) {
+ typeA = TPTR_TARGET(typeA);
+ typeB = TPTR_TARGET(typeB);
+ }
+ if (promotable_types_are_equal(typeA, typeB))
+ break;
+ }
+
+ CError_ASSERT(4617, table->rtype);
+
+ reg1 = ALLOC_VR();
+ reg2 = ALLOC_VR();
+ reg3 = outputReg ? outputReg : ALLOC_VR();
+
+ memclrw(&op1, sizeof(op1));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+
+ if (arg1->rtype == TYPE(&stvectorfloat)) {
+ emitpcode(PC_VSPLTISW, reg1, -1);
+ emitpcode(PC_VSLW, reg2, reg1, reg1);
+ emitpcode(table->opcode1, reg3, op1.reg, reg2);
+ } else {
+ emitpcode(PC_VSPLTISB, reg1, 0);
+ emitpcode(table->opcode1, reg2, reg1, op1.reg);
+ emitpcode(table->opcode2, reg3, op1.reg, reg2);
+ }
+
+ output->optype = OpndType_VR;
+ output->reg = reg3;
+}
+
+static void vector_intrinsic_abss(Intrinsics id, ENode *funccall, ENode *arg1, short outputReg, Operand *output) {
+ TypeTable22 *table;
+ Type *typeA;
+ Type *typeB;
+ short reg1;
+ short reg2;
+ short reg3;
+ Operand op1;
+
+ for (table = typeTable[id - Intrinsic_042]; table->rtype; table++) {
+ typeB = arg1->rtype;
+ typeA = table->arg1;
+ if (IS_TYPE_POINTER(typeA) && IS_TYPE_POINTER(typeB)) {
+ typeA = TPTR_TARGET(typeA);
+ typeB = TPTR_TARGET(typeB);
+ }
+ if (promotable_types_are_equal(typeA, typeB))
+ break;
+ }
+
+ CError_ASSERT(4683, table->rtype);
+
+ reg1 = ALLOC_VR();
+ reg2 = ALLOC_VR();
+ reg3 = outputReg ? outputReg : ALLOC_VR();
+
+ memclrw(&op1, sizeof(op1));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+
+ emitpcode(PC_VSPLTISB, reg1, 0);
+ emitpcode(table->opcode1, reg2, reg1, op1.reg);
+ emitpcode(table->opcode2, reg3, op1.reg, reg2);
+
+ output->optype = OpndType_VR;
+ output->reg = reg3;
+}
+
+static void vector_intrinsic_mtvscr(ENode *arg1, Operand *output, Opcode opcode) {
+ Operand op1;
+
+ memclrw(&op1, sizeof(op1));
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ emitpcode(opcode, op1.reg);
+}
+
+static void vector_predicate_2args(ENode *arg1, ENode *arg2, short outputReg, Operand *output, Opcode opcode, Intrinsics id) {
+ Operand op1;
+ Operand op2;
+ short reg1;
+ short reg2;
+ short reg3;
+ Opcode cond;
+
+ memclrw(&op1, sizeof(op1));
+ memclrw(&op2, sizeof(op2));
+
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+ GEN_NODE_TO_VR(arg2, &op2, arg2->rtype, 0);
+
+ reg1 = ALLOC_VR();
+ reg2 = op1.reg;
+ reg3 = op2.reg;
+ if (
+ ((id == Intrinsic_132 || id == Intrinsic_145) && arg1->rtype != TYPE(&stvectorfloat)) ||
+ ((id == Intrinsic_135 || id == Intrinsic_147) && arg1->rtype == TYPE(&stvectorfloat)) ||
+ id == Intrinsic_136 ||
+ id == Intrinsic_148 ||
+ id == Intrinsic_153 ||
+ id == Intrinsic_141 ||
+ id == Intrinsic_142 ||
+ id == Intrinsic_154
+ )
+ {
+ reg3 = op1.reg;
+ reg2 = op2.reg;
+ }
+ emitpcode(opcode, reg1, reg2, reg3);
+ pcsetrecordbit(pclastblock->lastPCode);
+
+ if (arg1->rtype == TYPE(&stvectorfloat)) {
+ switch (id) {
+ case Intrinsic_131:
+ case Intrinsic_132:
+ case Intrinsic_133:
+ case Intrinsic_135:
+ case Intrinsic_136:
+ cond = ELESS;
+ break;
+ case Intrinsic_150:
+ case Intrinsic_151:
+ case Intrinsic_152:
+ case Intrinsic_153:
+ case Intrinsic_154:
+ cond = EGREATEREQU;
+ break;
+ case Intrinsic_134:
+ case Intrinsic_138:
+ case Intrinsic_139:
+ case Intrinsic_140:
+ case Intrinsic_141:
+ case Intrinsic_142:
+ cond = EEQU;
+ break;
+ case Intrinsic_144:
+ case Intrinsic_145:
+ case Intrinsic_146:
+ case Intrinsic_147:
+ case Intrinsic_148:
+ case Intrinsic_156:
+ cond = ENOTEQU;
+ break;
+ default:
+ CError_FATAL(4805);
+ }
+ } else {
+ switch (id) {
+ case Intrinsic_131:
+ case Intrinsic_133:
+ case Intrinsic_136:
+ cond = ELESS;
+ break;
+ case Intrinsic_144:
+ case Intrinsic_146:
+ case Intrinsic_148:
+ cond = ENOTEQU;
+ break;
+ case Intrinsic_132:
+ case Intrinsic_135:
+ case Intrinsic_138:
+ cond = EEQU;
+ break;
+ case Intrinsic_145:
+ case Intrinsic_147:
+ case Intrinsic_150:
+ cond = EGREATEREQU;
+ break;
+ default:
+ CError_FATAL(4834);
+ }
+ }
+
+ output->optype = OpndType_CRField;
+ output->reg = 6;
+ output->regOffset = cond;
+}
+
+static void vector_predicate_1arg(ENode *arg1, short outputReg, Operand *output, Opcode opcode, Intrinsics id) {
+ Operand op1;
+ short reg;
+ Opcode cond;
+
+ memclrw(&op1, sizeof(op1));
+
+ GEN_NODE_TO_VR(arg1, &op1, arg1->rtype, 0);
+
+ reg = ALLOC_VR();
+ emitpcode(opcode, reg, op1.reg, op1.reg);
+ pcsetrecordbit(pclastblock->lastPCode);
+
+ switch (id) {
+ case Intrinsic_143:
+ cond = ELESS;
+ break;
+ case Intrinsic_149:
+ cond = EGREATEREQU;
+ break;
+ case Intrinsic_137:
+ cond = EEQU;
+ break;
+ case Intrinsic_155:
+ cond = ENOTEQU;
+ break;
+ default:
+ CError_FATAL(4878);
+ }
+
+ output->optype = OpndType_CRField;
+ output->reg = 6;
+ output->regOffset = cond;
+}
+
+ENode *Intrinsics_HandleIntrinsicCall(Object *func, ENodeList *args) {
+ ENode *callexpr;
+ Type *rtype;
+ Intrinsics id;
+
+ callexpr = NULL;
+
+ if (copts.altivec_model) {
+ id = func->u.func.u.intrinsicid;
+ switch (id) {
+ case Intrinsic_060:
+ case Intrinsic_061:
+ case Intrinsic_062:
+ case Intrinsic_063:
+ case Intrinsic_072:
+ case Intrinsic_073:
+ case Intrinsic_079:
+ case Intrinsic_080:
+ case Intrinsic_081:
+ case Intrinsic_082:
+ case Intrinsic_086:
+ case Intrinsic_093:
+ case Intrinsic_098:
+ case Intrinsic_100:
+ case Intrinsic_114:
+ case Intrinsic_115:
+ case Intrinsic_116:
+ case Intrinsic_202:
+ case Intrinsic_203:
+ case Intrinsic_224:
+ case Intrinsic_225:
+ case Intrinsic_226:
+ case Intrinsic_227:
+ case Intrinsic_228:
+ case Intrinsic_229:
+ case Intrinsic_230:
+ case Intrinsic_231:
+ case Intrinsic_240:
+ case Intrinsic_252:
+ case Intrinsic_259:
+ case Intrinsic_263:
+ case Intrinsic_280:
+ case Intrinsic_281:
+ case Intrinsic_282:
+ case Intrinsic_283:
+ case Intrinsic_284:
+ if (Intrinsics_VerifyParameterCount(3, args, func->name)) {
+ if ((rtype = Intrinsics_Verify3VectorArgs(id, args, func->name)))
+ callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype);
+ }
+ break;
+ case Intrinsic_042:
+ case Intrinsic_043:
+ case Intrinsic_044:
+ case Intrinsic_045:
+ case Intrinsic_046:
+ case Intrinsic_047:
+ case Intrinsic_049:
+ case Intrinsic_050:
+ case Intrinsic_051:
+ case Intrinsic_052:
+ case Intrinsic_053:
+ case Intrinsic_054:
+ case Intrinsic_055:
+ case Intrinsic_056:
+ case Intrinsic_057:
+ case Intrinsic_066:
+ case Intrinsic_067:
+ case Intrinsic_068:
+ case Intrinsic_070:
+ case Intrinsic_071:
+ case Intrinsic_074:
+ case Intrinsic_075:
+ case Intrinsic_076:
+ case Intrinsic_078:
+ case Intrinsic_084:
+ case Intrinsic_085:
+ case Intrinsic_087:
+ case Intrinsic_088:
+ case Intrinsic_089:
+ case Intrinsic_090:
+ case Intrinsic_091:
+ case Intrinsic_092:
+ case Intrinsic_095:
+ case Intrinsic_099:
+ case Intrinsic_101:
+ case Intrinsic_102:
+ case Intrinsic_103:
+ case Intrinsic_110:
+ case Intrinsic_111:
+ case Intrinsic_112:
+ case Intrinsic_113:
+ case Intrinsic_117:
+ case Intrinsic_118:
+ case Intrinsic_119:
+ case Intrinsic_120:
+ case Intrinsic_121:
+ case Intrinsic_122:
+ case Intrinsic_124:
+ case Intrinsic_125:
+ case Intrinsic_126:
+ case Intrinsic_127:
+ case Intrinsic_130:
+ case Intrinsic_131:
+ case Intrinsic_132:
+ case Intrinsic_133:
+ case Intrinsic_134:
+ case Intrinsic_135:
+ case Intrinsic_136:
+ case Intrinsic_138:
+ case Intrinsic_139:
+ case Intrinsic_140:
+ case Intrinsic_141:
+ case Intrinsic_142:
+ case Intrinsic_144:
+ case Intrinsic_145:
+ case Intrinsic_146:
+ case Intrinsic_147:
+ case Intrinsic_148:
+ case Intrinsic_150:
+ case Intrinsic_151:
+ case Intrinsic_152:
+ case Intrinsic_153:
+ case Intrinsic_154:
+ case Intrinsic_156:
+ case Intrinsic_157:
+ case Intrinsic_158:
+ case Intrinsic_159:
+ case Intrinsic_160:
+ case Intrinsic_161:
+ case Intrinsic_162:
+ case Intrinsic_163:
+ case Intrinsic_164:
+ case Intrinsic_165:
+ case Intrinsic_166:
+ case Intrinsic_167:
+ case Intrinsic_168:
+ case Intrinsic_169:
+ case Intrinsic_170:
+ case Intrinsic_171:
+ case Intrinsic_172:
+ case Intrinsic_173:
+ case Intrinsic_174:
+ case Intrinsic_175:
+ case Intrinsic_177:
+ case Intrinsic_178:
+ case Intrinsic_179:
+ case Intrinsic_180:
+ case Intrinsic_181:
+ case Intrinsic_182:
+ case Intrinsic_183:
+ case Intrinsic_184:
+ case Intrinsic_185:
+ case Intrinsic_186:
+ case Intrinsic_187:
+ case Intrinsic_188:
+ case Intrinsic_189:
+ case Intrinsic_190:
+ case Intrinsic_191:
+ case Intrinsic_192:
+ case Intrinsic_193:
+ case Intrinsic_196:
+ case Intrinsic_197:
+ case Intrinsic_198:
+ case Intrinsic_199:
+ case Intrinsic_200:
+ case Intrinsic_204:
+ case Intrinsic_205:
+ case Intrinsic_206:
+ case Intrinsic_207:
+ case Intrinsic_208:
+ case Intrinsic_209:
+ case Intrinsic_210:
+ case Intrinsic_211:
+ case Intrinsic_212:
+ case Intrinsic_213:
+ case Intrinsic_214:
+ case Intrinsic_215:
+ case Intrinsic_216:
+ case Intrinsic_217:
+ case Intrinsic_218:
+ case Intrinsic_219:
+ case Intrinsic_220:
+ case Intrinsic_221:
+ case Intrinsic_222:
+ case Intrinsic_223:
+ case Intrinsic_232:
+ case Intrinsic_233:
+ case Intrinsic_234:
+ case Intrinsic_235:
+ case Intrinsic_236:
+ case Intrinsic_237:
+ case Intrinsic_238:
+ case Intrinsic_239:
+ case Intrinsic_241:
+ case Intrinsic_242:
+ case Intrinsic_243:
+ case Intrinsic_244:
+ case Intrinsic_245:
+ case Intrinsic_246:
+ case Intrinsic_247:
+ case Intrinsic_248:
+ case Intrinsic_249:
+ case Intrinsic_250:
+ case Intrinsic_251:
+ case Intrinsic_254:
+ case Intrinsic_255:
+ case Intrinsic_256:
+ case Intrinsic_260:
+ case Intrinsic_261:
+ case Intrinsic_262:
+ case Intrinsic_264:
+ case Intrinsic_265:
+ case Intrinsic_266:
+ case Intrinsic_267:
+ case Intrinsic_268:
+ case Intrinsic_272:
+ case Intrinsic_273:
+ case Intrinsic_274:
+ case Intrinsic_275:
+ case Intrinsic_276:
+ case Intrinsic_277:
+ case Intrinsic_278:
+ case Intrinsic_279:
+ case Intrinsic_285:
+ case Intrinsic_286:
+ case Intrinsic_287:
+ case Intrinsic_288:
+ case Intrinsic_289:
+ case Intrinsic_290:
+ case Intrinsic_291:
+ case Intrinsic_292:
+ case Intrinsic_293:
+ case Intrinsic_294:
+ case Intrinsic_295:
+ case Intrinsic_296:
+ case Intrinsic_297:
+ case Intrinsic_298:
+ case Intrinsic_299:
+ case Intrinsic_300:
+ case Intrinsic_308:
+ if (Intrinsics_VerifyParameterCount(2, args, func->name)) {
+ if ((rtype = Intrinsics_Verify2VectorArgs(id, args, func->name)))
+ callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype);
+ }
+ break;
+ case Intrinsic_048:
+ case Intrinsic_058:
+ case Intrinsic_064:
+ case Intrinsic_065:
+ case Intrinsic_069:
+ case Intrinsic_083:
+ case Intrinsic_094:
+ case Intrinsic_096:
+ case Intrinsic_097:
+ case Intrinsic_104:
+ case Intrinsic_105:
+ case Intrinsic_106:
+ case Intrinsic_107:
+ case Intrinsic_108:
+ case Intrinsic_109:
+ case Intrinsic_123:
+ case Intrinsic_128:
+ case Intrinsic_129:
+ case Intrinsic_137:
+ case Intrinsic_143:
+ case Intrinsic_149:
+ case Intrinsic_155:
+ case Intrinsic_176:
+ case Intrinsic_194:
+ case Intrinsic_195:
+ case Intrinsic_201:
+ case Intrinsic_253:
+ case Intrinsic_257:
+ case Intrinsic_258:
+ case Intrinsic_269:
+ case Intrinsic_270:
+ case Intrinsic_271:
+ case Intrinsic_301:
+ case Intrinsic_302:
+ case Intrinsic_303:
+ case Intrinsic_304:
+ case Intrinsic_305:
+ case Intrinsic_306:
+ case Intrinsic_307:
+ if (Intrinsics_VerifyParameterCount(1, args, func->name)) {
+ if ((rtype = Intrinsics_Verify1VectorArg(id, args, func->name)))
+ callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype);
+ }
+ break;
+ case Intrinsic_059:
+ case Intrinsic_077:
+ if (Intrinsics_VerifyParameterCount(0, args, func->name)) {
+ if ((rtype = Intrinsics_VerifyNoVectorArgs(id, func->name)))
+ callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype);
+ }
+ break;
+ case Intrinsic_309:
+ case Intrinsic_310:
+ if (Intrinsics_VerifyParameterCount(1, args, func->name)) {
+ if ((rtype = Intrinsics_Verify1VectorArg2Ops(id, args, func->name)))
+ callexpr = Intrinsics_CreateIntrinsicFunc(func, args, rtype);
+ }
+ break;
+ }
+ }
+
+ return callexpr;
+}
+
+void call_intrinsic_function(ENode *funccall, short outputReg, Operand *output) {
+ ENodeList *args;
+ Object *object;
+ Intrinsics id;
+ Opcode op;
+ short reg;
+
+ static Opcode opcode[MaxIntrinsics] = {
+ /* Intrinsic_000 */ PC_EIEIO,
+ /* Intrinsic_001 */ PC_SYNC,
+ /* Intrinsic_002 */ PC_ISYNC,
+ 0,
+ 0,
+ /* Intrinsic_005 */ PC_FABS,
+ /* Intrinsic_006 */ PC_FNABS,
+ 0,
+ 0,
+ /* Intrinsic_009 */ PC_CNTLZW,
+ /* Intrinsic_010 */ PC_LHBRX,
+ /* Intrinsic_011 */ PC_LWBRX,
+ /* Intrinsic_012 */ PC_STHBRX,
+ /* Intrinsic_013 */ PC_STWBRX,
+ /* Intrinsic_014 */ PC_DCBF,
+ /* Intrinsic_015 */ PC_DCBT,
+ /* Intrinsic_016 */ PC_DCBST,
+ /* Intrinsic_017 */ PC_DCBTST,
+ /* Intrinsic_018 */ PC_DCBZ,
+ /* Intrinsic_019 */ PC_MULHW,
+ /* Intrinsic_020 */ PC_MULHWU,
+ /* Intrinsic_021 */ PC_DIVW,
+ /* Intrinsic_022 */ PC_DIVWU,
+ /* Intrinsic_023 */ PC_FMADD,
+ /* Intrinsic_024 */ PC_FMSUB,
+ /* Intrinsic_025 */ PC_FNMADD,
+ /* Intrinsic_026 */ PC_FNMSUB,
+ /* Intrinsic_027 */ PC_FMADDS,
+ /* Intrinsic_028 */ PC_FMSUBS,
+ /* Intrinsic_029 */ PC_FNMADDS,
+ /* Intrinsic_030 */ PC_FNMSUBS,
+ /* Intrinsic_031 */ PC_MFFS,
+ /* Intrinsic_032 */ PC_FRES,
+ /* Intrinsic_033 */ PC_FRSQRTE,
+ /* Intrinsic_004 */ PC_FSEL,
+ 0,
+ 0,
+ /* Intrinsic_037 */ PC_RLWIMI,
+ /* Intrinsic_038 */ PC_RLWINM,
+ /* Intrinsic_039 */ PC_RLWNM,
+ /* Intrinsic_040 */ PC_FABS,
+ /* Intrinsic_041 */ PC_FNABS
+ };
+
+ args = funccall->data.funccall.args;
+ object = funccall->data.funccall.funcref->data.objref;
+ id = object->u.func.u.intrinsicid;
+ cur_intrinsic_object = object;
+
+ switch (id) {
+ case Intrinsic_000:
+ case Intrinsic_001:
+ case Intrinsic_002:
+ appendpcode(pclastblock, makepcode(opcode[id]));
+ output->optype = OpndType_Absolute;
+ break;
+ case Intrinsic_003:
+ case Intrinsic_004:
+ abs_intrinsic(args->node, outputReg, output);
+ break;
+ case Intrinsic_005:
+ case Intrinsic_006:
+ case Intrinsic_032:
+ case Intrinsic_033:
+ case Intrinsic_040:
+ case Intrinsic_041:
+ fp_unary_operator(opcode[id], args->node, outputReg, output);
+ break;
+ case Intrinsic_007:
+ setflm_intrinsic(args->node, outputReg, output, funccall->ignored);
+ break;
+ case Intrinsic_008:
+ alloca_intrinsic(args->node, outputReg, output);
+ break;
+ case Intrinsic_009:
+ unary_operator(PC_CNTLZW, args->node, outputReg, output);
+ break;
+ case Intrinsic_010:
+ case Intrinsic_011:
+ load_bytereversed_intrinsic(opcode[id], args->node, args->next->node, outputReg, output);
+ break;
+ case Intrinsic_012:
+ case Intrinsic_013:
+ store_bytereversed_intrinsic(opcode[id], args->node, args->next->node, args->next->next->node);
+ output->optype = OpndType_Absolute;
+ break;
+ case Intrinsic_014:
+ case Intrinsic_015:
+ case Intrinsic_016:
+ case Intrinsic_017:
+ case Intrinsic_018:
+ data_cache_block_intrinsic(opcode[id], args->node, args->next->node);
+ output->optype = OpndType_Absolute;
+ break;
+ case Intrinsic_019:
+ case Intrinsic_020:
+ case Intrinsic_021:
+ case Intrinsic_022:
+ binary_operator(opcode[id], args->node, args->next->node, outputReg, output);
+ break;
+ case Intrinsic_023:
+ case Intrinsic_024:
+ case Intrinsic_025:
+ case Intrinsic_026:
+ case Intrinsic_027:
+ case Intrinsic_028:
+ case Intrinsic_029:
+ case Intrinsic_030:
+ case Intrinsic_034:
+ fp_multiply_add(opcode[id],
+ args->node, args->next->node, args->next->next->node,
+ outputReg, output);
+ break;
+ case Intrinsic_031:
+ reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_MFFS, output->reg = reg);
+ output->optype = OpndType_FPR;
+ break;
+ case Intrinsic_035:
+ call_function(funccall, output);
+ break;
+ case Intrinsic_036:
+ if (ENODE_IS(args->next->next->node, EINTCONST))
+ memcpy_intrinsic(
+ args->node, args->next->node, args->next->next->node->data.intval.lo,
+ funccall->ignored, output);
+ else
+ call_function(funccall, output);
+ break;
+ case Intrinsic_037:
+ rlwimi_intrinsic(
+ args->node,
+ args->next->node,
+ args->next->next->node,
+ args->next->next->next->node,
+ args->next->next->next->next->node,
+ outputReg, output);
+ break;
+ case Intrinsic_038:
+ rlwinm_intrinsic(
+ args->node,
+ args->next->node,
+ args->next->next->node,
+ args->next->next->next->node,
+ outputReg, output);
+ break;
+ case Intrinsic_039:
+ rlwnm_intrinsic(
+ args->node,
+ args->next->node,
+ args->next->next->node,
+ args->next->next->next->node,
+ outputReg, output);
+ break;
+ case Intrinsic_072:
+ case Intrinsic_073:
+ case Intrinsic_079:
+ case Intrinsic_080:
+ case Intrinsic_081:
+ case Intrinsic_082:
+ case Intrinsic_086:
+ case Intrinsic_093:
+ case Intrinsic_098:
+ case Intrinsic_202:
+ case Intrinsic_203:
+ case Intrinsic_224:
+ case Intrinsic_225:
+ case Intrinsic_226:
+ case Intrinsic_227:
+ case Intrinsic_228:
+ case Intrinsic_229:
+ case Intrinsic_230:
+ case Intrinsic_231:
+ case Intrinsic_240:
+ case Intrinsic_252:
+ case Intrinsic_259:
+ op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node);
+ vector_intrinsic_3args(args->node, args->next->node, args->next->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_100:
+ case Intrinsic_263:
+ op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node);
+ vector_intrinsic_sld(args->node, args->next->node, args->next->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_042:
+ case Intrinsic_043:
+ case Intrinsic_044:
+ case Intrinsic_045:
+ case Intrinsic_046:
+ case Intrinsic_047:
+ case Intrinsic_049:
+ case Intrinsic_050:
+ case Intrinsic_051:
+ case Intrinsic_053:
+ case Intrinsic_074:
+ case Intrinsic_075:
+ case Intrinsic_076:
+ case Intrinsic_078:
+ case Intrinsic_084:
+ case Intrinsic_085:
+ case Intrinsic_087:
+ case Intrinsic_088:
+ case Intrinsic_089:
+ case Intrinsic_090:
+ case Intrinsic_091:
+ case Intrinsic_092:
+ case Intrinsic_095:
+ case Intrinsic_099:
+ case Intrinsic_101:
+ case Intrinsic_102:
+ case Intrinsic_110:
+ case Intrinsic_111:
+ case Intrinsic_112:
+ case Intrinsic_113:
+ case Intrinsic_117:
+ case Intrinsic_118:
+ case Intrinsic_119:
+ case Intrinsic_120:
+ case Intrinsic_121:
+ case Intrinsic_122:
+ case Intrinsic_124:
+ case Intrinsic_125:
+ case Intrinsic_126:
+ case Intrinsic_127:
+ case Intrinsic_130:
+ case Intrinsic_157:
+ case Intrinsic_158:
+ case Intrinsic_159:
+ case Intrinsic_160:
+ case Intrinsic_161:
+ case Intrinsic_162:
+ case Intrinsic_163:
+ case Intrinsic_164:
+ case Intrinsic_165:
+ case Intrinsic_166:
+ case Intrinsic_167:
+ case Intrinsic_168:
+ case Intrinsic_169:
+ case Intrinsic_170:
+ case Intrinsic_171:
+ case Intrinsic_172:
+ case Intrinsic_173:
+ case Intrinsic_174:
+ case Intrinsic_175:
+ case Intrinsic_177:
+ case Intrinsic_178:
+ case Intrinsic_179:
+ case Intrinsic_180:
+ case Intrinsic_181:
+ case Intrinsic_182:
+ case Intrinsic_183:
+ case Intrinsic_184:
+ case Intrinsic_185:
+ case Intrinsic_186:
+ case Intrinsic_187:
+ case Intrinsic_188:
+ case Intrinsic_189:
+ case Intrinsic_204:
+ case Intrinsic_205:
+ case Intrinsic_206:
+ case Intrinsic_207:
+ case Intrinsic_208:
+ case Intrinsic_209:
+ case Intrinsic_210:
+ case Intrinsic_211:
+ case Intrinsic_212:
+ case Intrinsic_213:
+ case Intrinsic_214:
+ case Intrinsic_215:
+ case Intrinsic_216:
+ case Intrinsic_217:
+ case Intrinsic_218:
+ case Intrinsic_219:
+ case Intrinsic_220:
+ case Intrinsic_221:
+ case Intrinsic_222:
+ case Intrinsic_223:
+ case Intrinsic_232:
+ case Intrinsic_233:
+ case Intrinsic_234:
+ case Intrinsic_235:
+ case Intrinsic_236:
+ case Intrinsic_237:
+ case Intrinsic_238:
+ case Intrinsic_239:
+ case Intrinsic_241:
+ case Intrinsic_242:
+ case Intrinsic_243:
+ case Intrinsic_244:
+ case Intrinsic_245:
+ case Intrinsic_246:
+ case Intrinsic_247:
+ case Intrinsic_248:
+ case Intrinsic_249:
+ case Intrinsic_250:
+ case Intrinsic_251:
+ case Intrinsic_254:
+ case Intrinsic_255:
+ case Intrinsic_256:
+ case Intrinsic_260:
+ case Intrinsic_261:
+ case Intrinsic_262:
+ case Intrinsic_264:
+ case Intrinsic_265:
+ case Intrinsic_272:
+ case Intrinsic_273:
+ case Intrinsic_274:
+ case Intrinsic_275:
+ case Intrinsic_276:
+ case Intrinsic_277:
+ case Intrinsic_278:
+ case Intrinsic_279:
+ case Intrinsic_285:
+ case Intrinsic_286:
+ case Intrinsic_287:
+ case Intrinsic_288:
+ case Intrinsic_289:
+ case Intrinsic_290:
+ case Intrinsic_291:
+ case Intrinsic_292:
+ case Intrinsic_293:
+ case Intrinsic_294:
+ case Intrinsic_295:
+ case Intrinsic_296:
+ case Intrinsic_297:
+ case Intrinsic_298:
+ case Intrinsic_299:
+ case Intrinsic_300:
+ case Intrinsic_308:
+ op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node);
+ vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_048:
+ case Intrinsic_064:
+ case Intrinsic_065:
+ case Intrinsic_069:
+ case Intrinsic_094:
+ case Intrinsic_096:
+ case Intrinsic_097:
+ case Intrinsic_123:
+ case Intrinsic_128:
+ case Intrinsic_129:
+ case Intrinsic_176:
+ case Intrinsic_194:
+ case Intrinsic_195:
+ case Intrinsic_201:
+ case Intrinsic_253:
+ case Intrinsic_257:
+ case Intrinsic_258:
+ case Intrinsic_301:
+ case Intrinsic_302:
+ case Intrinsic_303:
+ case Intrinsic_304:
+ case Intrinsic_305:
+ case Intrinsic_306:
+ case Intrinsic_307:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_intrinsic_1arg(args->node, outputReg, output, op);
+ break;
+ case Intrinsic_055:
+ case Intrinsic_056:
+ case Intrinsic_057:
+ case Intrinsic_103:
+ case Intrinsic_190:
+ case Intrinsic_191:
+ case Intrinsic_192:
+ case Intrinsic_193:
+ case Intrinsic_266:
+ case Intrinsic_267:
+ case Intrinsic_268:
+ op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node);
+ vector_intrinsic_2args1const(args->node, args->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_104:
+ case Intrinsic_105:
+ case Intrinsic_106:
+ case Intrinsic_269:
+ case Intrinsic_270:
+ case Intrinsic_271:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_intrinsic_splats(args->node, outputReg, output, op);
+ break;
+ case Intrinsic_107:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_intrinsic_splatu8(args->node, outputReg, output, op);
+ break;
+ case Intrinsic_108:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_intrinsic_splatu16(args->node, outputReg, output, op);
+ break;
+ case Intrinsic_109:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_intrinsic_splatu32(args->node, outputReg, output, op);
+ break;
+ case Intrinsic_083:
+ vector_intrinsic_mtvscr(args->node, output, PC_MTVSCR);
+ break;
+ case Intrinsic_077:
+ op = Intrinsics_FindOpcodeNoArgs(id, funccall);
+ vector_intrinsic_mfvscr(outputReg, op, output);
+ break;
+ case Intrinsic_058:
+ vector_intrinsic_dss(args->node);
+ break;
+ case Intrinsic_059:
+ op = Intrinsics_FindOpcodeNoArgs(id, funccall);
+ vector_intrinsic_no_args(op);
+ break;
+ case Intrinsic_060:
+ case Intrinsic_061:
+ case Intrinsic_062:
+ case Intrinsic_063:
+ switch (id) {
+ case Intrinsic_060:
+ op = PC_DST;
+ break;
+ case Intrinsic_061:
+ op = PC_DSTST;
+ break;
+ case Intrinsic_062:
+ op = PC_DSTSTT;
+ break;
+ case Intrinsic_063:
+ op = PC_DSTT;
+ break;
+ }
+ vector_intrinsic_datastream(args->node, args->next->node, args->next->next->node, op);
+ break;
+ case Intrinsic_066:
+ case Intrinsic_067:
+ case Intrinsic_068:
+ case Intrinsic_070:
+ case Intrinsic_071:
+ case Intrinsic_196:
+ case Intrinsic_197:
+ case Intrinsic_198:
+ case Intrinsic_199:
+ case Intrinsic_200:
+ op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node);
+ vector_intrinsic_load(args->node, args->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_114:
+ case Intrinsic_115:
+ case Intrinsic_116:
+ case Intrinsic_280:
+ case Intrinsic_281:
+ case Intrinsic_282:
+ case Intrinsic_283:
+ case Intrinsic_284:
+ op = Intrinsics_FindOpcode3Args(id, funccall, args->node, args->next->node, args->next->next->node);
+ vector_intrinsic_store(args->node, args->next->node, args->next->next->node, outputReg, output, op);
+ break;
+ case Intrinsic_131:
+ case Intrinsic_132:
+ case Intrinsic_133:
+ case Intrinsic_134:
+ case Intrinsic_135:
+ case Intrinsic_136:
+ case Intrinsic_138:
+ case Intrinsic_139:
+ case Intrinsic_140:
+ case Intrinsic_141:
+ case Intrinsic_142:
+ case Intrinsic_144:
+ case Intrinsic_145:
+ case Intrinsic_146:
+ case Intrinsic_147:
+ case Intrinsic_148:
+ case Intrinsic_150:
+ case Intrinsic_151:
+ case Intrinsic_152:
+ case Intrinsic_153:
+ case Intrinsic_154:
+ case Intrinsic_156:
+ op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node);
+ vector_predicate_2args(args->node, args->next->node, outputReg, output, op, id);
+ break;
+ case Intrinsic_137:
+ case Intrinsic_143:
+ case Intrinsic_149:
+ case Intrinsic_155:
+ op = Intrinsics_FindOpcode1Arg(id, funccall, args->node);
+ vector_predicate_1arg(args->node, outputReg, output, op, id);
+ break;
+ case Intrinsic_309:
+ vector_intrinsic_abs(id, funccall, args->node, outputReg, output);
+ break;
+ case Intrinsic_310:
+ vector_intrinsic_abss(id, funccall, args->node, outputReg, output);
+ break;
+ case Intrinsic_052:
+ case Intrinsic_054:
+ op = Intrinsics_FindOpcode2Args(id, funccall, args->node, args->next->node);
+ vector_intrinsic_2args(args->node, args->next->node, outputReg, output, op);
+ break;
+ default:
+ CError_FATAL(6152);
+ }
+}
+
+void Intrinsics_SetupRuntimeObjects(void) {
+ static TypePointer char_ptr = {TYPEPOINTER, 4, TYPE(&stchar), 0};
+ Boolean savecpp;
+ int i;
+
+ savecpp = copts.cplusplus;
+ copts.cplusplus = 0;
+
+ for (i = 0; i < MaxIntrinsics; i++)
+ intrinsics[i] = NULL;
+
+ intrinsics[Intrinsic_000] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__eieio"), 0, 0);
+ intrinsics[Intrinsic_001] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sync"), 0, 0);
+ intrinsics[Intrinsic_002] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__isync"), 0, 0);
+ intrinsics[Intrinsic_003] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__abs"), 0, 1, &stsignedint);
+ intrinsics[Intrinsic_004] = CParser_NewRTFunc(TYPE(&stsignedlong), GetHashNameNodeExport("__labs"), 0, 1, &stsignedlong);
+ intrinsics[Intrinsic_005] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fabs"), 0, 1, &stdouble);
+ intrinsics[Intrinsic_006] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnabs"), 0, 1, &stdouble);
+ intrinsics[Intrinsic_007] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__setflm"), 0, 1, &stdouble);
+ intrinsics[Intrinsic_033] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__frsqrte"), 0, 1, &stdouble);
+ intrinsics[Intrinsic_008] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__alloca"), 0, 1, &stunsignedint);
+ intrinsics[Intrinsic_009] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__cntlzw"), 0, 1, &stunsignedint);
+ intrinsics[Intrinsic_010] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lhbrx"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_011] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__lwbrx"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_012] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__sthbrx"), 0, 3, &stunsignedshort, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_013] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__stwbrx"), 0, 3, &stunsignedint, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_014] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbf"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_015] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbt"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_016] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbst"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_017] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbtst"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_018] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("__dcbz"), 0, 2, &void_ptr, &stsignedint);
+ intrinsics[Intrinsic_019] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__mulhw"), 0, 2, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_020] = CParser_NewRTFunc(TYPE(&stunsignedint), GetHashNameNodeExport("__mulhwu"), 0, 2, &stunsignedint, &stunsignedint);
+ intrinsics[Intrinsic_021] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divw"), 0, 2, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_022] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__divwu"), 0, 2, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_023] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmadd"), 0, 3, &stdouble, &stdouble, &stdouble);
+ intrinsics[Intrinsic_024] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fmsub"), 0, 3, &stdouble, &stdouble, &stdouble);
+ intrinsics[Intrinsic_025] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmadd"), 0, 3, &stdouble, &stdouble, &stdouble);
+ intrinsics[Intrinsic_026] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fnmsub"), 0, 3, &stdouble, &stdouble, &stdouble);
+ intrinsics[Intrinsic_034] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__fsel"), 0, 3, &stdouble, &stdouble, &stdouble);
+ intrinsics[Intrinsic_027] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmadds"), 0, 3, &stfloat, &stfloat, &stfloat);
+ intrinsics[Intrinsic_028] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fmsubs"), 0, 3, &stfloat, &stfloat, &stfloat);
+ intrinsics[Intrinsic_029] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmadds"), 0, 3, &stfloat, &stfloat, &stfloat);
+ intrinsics[Intrinsic_030] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnmsubs"), 0, 3, &stfloat, &stfloat, &stfloat);
+ intrinsics[Intrinsic_031] = CParser_NewRTFunc(TYPE(&stdouble), GetHashNameNodeExport("__mffs"), 0, 0);
+ intrinsics[Intrinsic_032] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fres"), 0, 1, &stfloat);
+ intrinsics[Intrinsic_040] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fabsf"), 0, 1, &stfloat);
+ intrinsics[Intrinsic_041] = CParser_NewRTFunc(TYPE(&stfloat), GetHashNameNodeExport("__fnabsf"), 0, 1, &stfloat);
+ intrinsics[Intrinsic_035] = CParser_NewRTFunc(TYPE(&char_ptr), GetHashNameNodeExport("__strcpy"), 0, 2, &char_ptr, &char_ptr);
+ TYPE_FUNC(intrinsics[Intrinsic_035]->type)->args->next->qual |= Q_CONST;
+ intrinsics[Intrinsic_036] = CParser_NewRTFunc(TYPE(&void_ptr), GetHashNameNodeExport("__memcpy"), 0, 3, &void_ptr, &void_ptr, &stunsignedlong);
+ __memcpy_object = intrinsics[Intrinsic_036];
+ TYPE_FUNC(intrinsics[Intrinsic_036]->type)->args->next->qual |= Q_CONST;
+ intrinsics[Intrinsic_037] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwimi"), 0, 5, &stsignedint, &stsignedint, &stsignedint, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_038] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwinm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_039] = CParser_NewRTFunc(TYPE(&stsignedint), GetHashNameNodeExport("__rlwnm"), 0, 4, &stsignedint, &stsignedint, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_042] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_add"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_043] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_addc"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_044] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_adds"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_045] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_and"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_046] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_andc"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_047] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_avg"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_048] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ceil"), 0, 1, &stvector);
+ intrinsics[Intrinsic_049] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_050] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpeq"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_051] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpge"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_052] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmple"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_053] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmpgt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_054] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cmplt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_055] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctf"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_056] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_cts"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_057] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ctu"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_058] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dss"), 0, 1, &stsignedint);
+ intrinsics[Intrinsic_059] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dssall"), 0, 0);
+ intrinsics[Intrinsic_060] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dst"), 0, 3, &stvector, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_061] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstst"), 0, 3, &stvector, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_062] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dststt"), 0, 3, &stvector, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_063] = CParser_NewRTFunc(&stvoid, GetHashNameNodeExport("vec_dstt"), 0, 3, &stvector, &stsignedint, &stsignedint);
+ intrinsics[Intrinsic_064] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_expte"), 0, 1, &stvector);
+ intrinsics[Intrinsic_065] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_floor"), 0, 1, &stvector);
+ intrinsics[Intrinsic_066] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ld"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_067] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lde"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_068] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ldl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_069] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_loge"), 0, 1, &stvector);
+ intrinsics[Intrinsic_070] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_071] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvsr"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_072] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madd"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_073] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_madds"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_074] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_max"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_075] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergeh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_076] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mergel"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_077] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mfvscr"), 0, 0);
+ intrinsics[Intrinsic_078] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_min"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_079] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mladd"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_080] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mradds"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_081] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msum"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_082] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_msums"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_083] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mtvscr"), 0, 1, &stvector);
+ intrinsics[Intrinsic_084] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mule"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_085] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_mulo"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_086] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nmsub"), 0, 2, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_087] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_nor"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_088] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_or"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_089] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_pack"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_090] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packpx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_091] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_092] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_packsu"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_093] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_perm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_094] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_re"), 0, 1, &stvector);
+ intrinsics[Intrinsic_095] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_096] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_round"), 0, 1, &stvector);
+ intrinsics[Intrinsic_097] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_rsqrte"), 0, 1, &stvector);
+ intrinsics[Intrinsic_098] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sel"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_099] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_100] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sld"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_101] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sll"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_102] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_slo"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_103] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_104] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s8"), 0, 1, &stvector);
+ intrinsics[Intrinsic_105] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s16"), 0, 1, &stvector);
+ intrinsics[Intrinsic_106] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_s32"), 0, 1, &stvector);
+ intrinsics[Intrinsic_107] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u8"), 0, 1, &stvector);
+ intrinsics[Intrinsic_108] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u16"), 0, 1, &stvector);
+ intrinsics[Intrinsic_109] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_splat_u32"), 0, 1, &stvector);
+ intrinsics[Intrinsic_110] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sr"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_111] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sra"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_112] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_srl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_113] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sro"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_114] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_st"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_115] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_ste"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_116] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stl"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_117] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_118] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subc"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_119] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_subs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_120] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum4s"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_121] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sum2s"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_122] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_sums"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_123] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_trunc"), 0, 1, &stvector);
+ intrinsics[Intrinsic_124] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_125] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2sl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_126] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2uh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_127] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpack2ul"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_128] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackh"), 0, 1, &stvector);
+ intrinsics[Intrinsic_129] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_unpackl"), 0, 1, &stvector);
+ intrinsics[Intrinsic_130] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_xor"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_131] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_eq"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_132] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ge"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_133] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_gt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_134] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_in"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_135] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_le"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_136] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_lt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_137] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nan"), 0, 1, &stvector);
+ intrinsics[Intrinsic_138] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ne"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_139] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nge"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_140] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_ngt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_141] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nle"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_142] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_nlt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_143] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_all_numeric"), 0, 1, &stvector);
+ intrinsics[Intrinsic_144] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_eq"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_145] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ge"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_146] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_gt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_147] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_le"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_148] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_lt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_149] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nan"), 0, 1, &stvector);
+ intrinsics[Intrinsic_150] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ne"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_151] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nge"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_152] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_ngt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_153] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nle"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_154] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_nlt"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_155] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_numeric"), 0, 1, &stvector);
+ intrinsics[Intrinsic_156] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_any_out"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_157] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_158] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_159] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduwm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_160] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_161] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddcuw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_162] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddubs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_163] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsbs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_164] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduhs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_165] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddshs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_166] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vadduws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_167] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vaddsws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_168] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vand"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_169] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vandc"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_170] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_171] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_172] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_173] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_174] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavguw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_175] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vavgsw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_176] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfip"), 0, 1, &stvector);
+ intrinsics[Intrinsic_177] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpbfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_178] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_179] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_180] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpequw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_181] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpeqfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_182] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgefp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_183] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_184] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_185] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_186] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_187] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtuw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_188] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtsw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_189] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcmpgtfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_190] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfux"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_191] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vcfsx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_192] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctsxs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_193] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vctuxs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_194] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vexptefp"), 0, 1, &stvector);
+ intrinsics[Intrinsic_195] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfim"), 0, 1, &stvector);
+ intrinsics[Intrinsic_196] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_197] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvebx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_198] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvehx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_199] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvewx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_200] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_lvxl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_201] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vlogefp"), 0, 1, &stvector);
+ intrinsics[Intrinsic_202] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaddfp"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_203] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhaddshs"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_204] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_205] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_206] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_207] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_208] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxuw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_209] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxsw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_210] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmaxfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_211] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_212] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_213] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrghw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_214] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_215] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_216] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmrglw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_217] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_218] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_219] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_220] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_221] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminuw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_222] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminsw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_223] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vminfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_224] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmladduhm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_225] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmhraddshs"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_226] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumubm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_227] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_228] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsummbm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_229] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_230] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumuhs"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_231] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmsumshs"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_232] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_233] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_234] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuleuh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_235] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulesh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_236] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmuloub"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_237] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_238] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulouh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_239] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vmulosh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_240] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnmsubfp"), 0, 2, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_241] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vnor"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_242] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vor"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_243] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhum"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_244] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwum"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_245] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkpx"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_246] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuhus"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_247] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshss"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_248] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkuwus"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_249] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswss"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_250] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkshus"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_251] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vpkswus"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_252] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vperm"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_253] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrefp"), 0, 1, &stvector);
+ intrinsics[Intrinsic_254] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_255] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_256] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrlw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_257] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfin"), 0, 1, &stvector);
+ intrinsics[Intrinsic_258] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrsqrtefp"), 0, 1, &stvector);
+ intrinsics[Intrinsic_259] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsel"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_260] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_261] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_262] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_263] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsldoi"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_264] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsl"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_265] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vslo"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_266] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_267] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsplth"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_268] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_269] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisb"), 0, 1, &stvector);
+ intrinsics[Intrinsic_270] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltish"), 0, 1, &stvector);
+ intrinsics[Intrinsic_271] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vspltisw"), 0, 1, &stvector);
+ intrinsics[Intrinsic_272] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrb"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_273] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrh"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_274] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_275] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrab"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_276] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsrah"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_277] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsraw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_278] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsr"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_279] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsro"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_280] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvx"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_281] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvebx"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_282] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvehx"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_283] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvewx"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_284] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_stvxl"), 0, 3, &stvector, &stvector, &stvector);
+ intrinsics[Intrinsic_285] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_286] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_287] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuwm"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_288] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubfp"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_289] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubcuw"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_290] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsububs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_291] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsbs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_292] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuhs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_293] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubshs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_294] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubuws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_295] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsubsws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_296] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4ubs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_297] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4sbs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_298] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum4shs"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_299] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsum2sws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_300] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vsumsws"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_301] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vrfiz"), 0, 1, &stvector);
+ intrinsics[Intrinsic_302] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsb"), 0, 1, &stvector);
+ intrinsics[Intrinsic_303] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsb"), 0, 1, &stvector);
+ intrinsics[Intrinsic_304] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhpx"), 0, 1, &stvector);
+ intrinsics[Intrinsic_305] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklpx"), 0, 1, &stvector);
+ intrinsics[Intrinsic_306] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupkhsh"), 0, 1, &stvector);
+ intrinsics[Intrinsic_307] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vupklsh"), 0, 1, &stvector);
+ intrinsics[Intrinsic_308] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_vxor"), 0, 2, &stvector, &stvector);
+ intrinsics[Intrinsic_309] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abs"), 0, 1, &stvector);
+ intrinsics[Intrinsic_310] = CParser_NewRTFunc(TYPE(&stvector), GetHashNameNodeExport("vec_abss"), 0, 1, &stvector);
+
+ for (i = 0; i < MaxIntrinsics; i++) {
+ CError_ASSERT(6600, intrinsics[i]);
+ intrinsics[i]->u.func.u.intrinsicid = i;
+ TYPE_FUNC(intrinsics[i]->type)->flags |= FUNC_INTRINSIC;
+ CScope_AddGlobalObject(intrinsics[i]);
+ }
+
+ copts.cplusplus = savecpp;
+}
+
+static Object *CheckRuntimeObject(char *name) {
+ NameSpaceName *nsname = CScope_FindNameSpaceName(cscope_root, GetHashNameNodeExport(name));
+
+ if (!nsname)
+ return NULL;
+
+ if (nsname->first.object && nsname->first.next == NULL)
+ return OBJECT(nsname->first.object);
+
+ return NULL;
+}
+
+Boolean Intrinsics_ReInitRuntimeObjects(Boolean flag) {
+ if (flag) {
+ if (!(intrinsics[Intrinsic_000] = CheckRuntimeObject("__eieio"))) return 0;
+ if (!(intrinsics[Intrinsic_001] = CheckRuntimeObject("__sync"))) return 0;
+ if (!(intrinsics[Intrinsic_002] = CheckRuntimeObject("__isync"))) return 0;
+ if (!(intrinsics[Intrinsic_003] = CheckRuntimeObject("__abs"))) return 0;
+ if (!(intrinsics[Intrinsic_004] = CheckRuntimeObject("__labs"))) return 0;
+ if (!(intrinsics[Intrinsic_005] = CheckRuntimeObject("__fabs"))) return 0;
+ if (!(intrinsics[Intrinsic_006] = CheckRuntimeObject("__fnabs"))) return 0;
+ if (!(intrinsics[Intrinsic_007] = CheckRuntimeObject("__setflm"))) return 0;
+ if (!(intrinsics[Intrinsic_033] = CheckRuntimeObject("__frsqrte"))) return 0;
+ if (!(intrinsics[Intrinsic_008] = CheckRuntimeObject("__alloca"))) return 0;
+ if (!(intrinsics[Intrinsic_009] = CheckRuntimeObject("__cntlzw"))) return 0;
+ if (!(intrinsics[Intrinsic_010] = CheckRuntimeObject("__lhbrx"))) return 0;
+ if (!(intrinsics[Intrinsic_011] = CheckRuntimeObject("__lwbrx"))) return 0;
+ if (!(intrinsics[Intrinsic_012] = CheckRuntimeObject("__sthbrx"))) return 0;
+ if (!(intrinsics[Intrinsic_013] = CheckRuntimeObject("__stwbrx"))) return 0;
+ if (!(intrinsics[Intrinsic_014] = CheckRuntimeObject("__dcbf"))) return 0;
+ if (!(intrinsics[Intrinsic_015] = CheckRuntimeObject("__dcbt"))) return 0;
+ if (!(intrinsics[Intrinsic_016] = CheckRuntimeObject("__dcbst"))) return 0;
+ if (!(intrinsics[Intrinsic_017] = CheckRuntimeObject("__dcbtst"))) return 0;
+ if (!(intrinsics[Intrinsic_018] = CheckRuntimeObject("__dcbz"))) return 0;
+ if (!(intrinsics[Intrinsic_019] = CheckRuntimeObject("__mulhw"))) return 0;
+ if (!(intrinsics[Intrinsic_020] = CheckRuntimeObject("__mulhwu"))) return 0;
+ if (!(intrinsics[Intrinsic_021] = CheckRuntimeObject("__divw"))) return 0;
+ if (!(intrinsics[Intrinsic_022] = CheckRuntimeObject("__divwu"))) return 0;
+ if (!(intrinsics[Intrinsic_023] = CheckRuntimeObject("__fmadd"))) return 0;
+ if (!(intrinsics[Intrinsic_024] = CheckRuntimeObject("__fmsub"))) return 0;
+ if (!(intrinsics[Intrinsic_025] = CheckRuntimeObject("__fnmadd"))) return 0;
+ if (!(intrinsics[Intrinsic_026] = CheckRuntimeObject("__fnmsub"))) return 0;
+ if (!(intrinsics[Intrinsic_034] = CheckRuntimeObject("__fsel"))) return 0;
+ if (!(intrinsics[Intrinsic_027] = CheckRuntimeObject("__fmadds"))) return 0;
+ if (!(intrinsics[Intrinsic_028] = CheckRuntimeObject("__fmsubs"))) return 0;
+ if (!(intrinsics[Intrinsic_029] = CheckRuntimeObject("__fnmadds"))) return 0;
+ if (!(intrinsics[Intrinsic_030] = CheckRuntimeObject("__fnmsubs"))) return 0;
+ if (!(intrinsics[Intrinsic_031] = CheckRuntimeObject("__mffs"))) return 0;
+ if (!(intrinsics[Intrinsic_032] = CheckRuntimeObject("__fres"))) return 0;
+ if (!(intrinsics[Intrinsic_040] = CheckRuntimeObject("__fabsf"))) return 0;
+ if (!(intrinsics[Intrinsic_041] = CheckRuntimeObject("__fnabsf"))) return 0;
+ if (!(intrinsics[Intrinsic_035] = CheckRuntimeObject("__strcpy"))) return 0;
+ if (!(intrinsics[Intrinsic_037] = CheckRuntimeObject("__rlwimi"))) return 0;
+ if (!(intrinsics[Intrinsic_038] = CheckRuntimeObject("__rlwinm"))) return 0;
+ if (!(intrinsics[Intrinsic_039] = CheckRuntimeObject("__rlwnm"))) return 0;
+ if (!(intrinsics[Intrinsic_042] = CheckRuntimeObject("vec_add"))) return 0;
+ if (!(intrinsics[Intrinsic_043] = CheckRuntimeObject("vec_addc"))) return 0;
+ if (!(intrinsics[Intrinsic_044] = CheckRuntimeObject("vec_adds"))) return 0;
+ if (!(intrinsics[Intrinsic_045] = CheckRuntimeObject("vec_and"))) return 0;
+ if (!(intrinsics[Intrinsic_046] = CheckRuntimeObject("vec_andc"))) return 0;
+ if (!(intrinsics[Intrinsic_047] = CheckRuntimeObject("vec_avg"))) return 0;
+ if (!(intrinsics[Intrinsic_048] = CheckRuntimeObject("vec_ceil"))) return 0;
+ if (!(intrinsics[Intrinsic_049] = CheckRuntimeObject("vec_cmpb"))) return 0;
+ if (!(intrinsics[Intrinsic_050] = CheckRuntimeObject("vec_cmpeq"))) return 0;
+ if (!(intrinsics[Intrinsic_051] = CheckRuntimeObject("vec_cmpge"))) return 0;
+ if (!(intrinsics[Intrinsic_052] = CheckRuntimeObject("vec_cmple"))) return 0;
+ if (!(intrinsics[Intrinsic_053] = CheckRuntimeObject("vec_cmpgt"))) return 0;
+ if (!(intrinsics[Intrinsic_054] = CheckRuntimeObject("vec_cmplt"))) return 0;
+ if (!(intrinsics[Intrinsic_055] = CheckRuntimeObject("vec_ctf"))) return 0;
+ if (!(intrinsics[Intrinsic_056] = CheckRuntimeObject("vec_cts"))) return 0;
+ if (!(intrinsics[Intrinsic_057] = CheckRuntimeObject("vec_ctu"))) return 0;
+ if (!(intrinsics[Intrinsic_064] = CheckRuntimeObject("vec_expte"))) return 0;
+ if (!(intrinsics[Intrinsic_065] = CheckRuntimeObject("vec_floor"))) return 0;
+ if (!(intrinsics[Intrinsic_066] = CheckRuntimeObject("vec_ld"))) return 0;
+ if (!(intrinsics[Intrinsic_067] = CheckRuntimeObject("vec_lde"))) return 0;
+ if (!(intrinsics[Intrinsic_068] = CheckRuntimeObject("vec_ldl"))) return 0;
+ if (!(intrinsics[Intrinsic_069] = CheckRuntimeObject("vec_loge"))) return 0;
+ if (!(intrinsics[Intrinsic_070] = CheckRuntimeObject("vec_lvsl"))) return 0;
+ if (!(intrinsics[Intrinsic_071] = CheckRuntimeObject("vec_lvsr"))) return 0;
+ if (!(intrinsics[Intrinsic_072] = CheckRuntimeObject("vec_madd"))) return 0;
+ if (!(intrinsics[Intrinsic_073] = CheckRuntimeObject("vec_madds"))) return 0;
+ if (!(intrinsics[Intrinsic_074] = CheckRuntimeObject("vec_max"))) return 0;
+ if (!(intrinsics[Intrinsic_075] = CheckRuntimeObject("vec_mergeh"))) return 0;
+ if (!(intrinsics[Intrinsic_076] = CheckRuntimeObject("vec_mergel"))) return 0;
+ if (!(intrinsics[Intrinsic_077] = CheckRuntimeObject("vec_mfvscr"))) return 0;
+ if (!(intrinsics[Intrinsic_078] = CheckRuntimeObject("vec_min"))) return 0;
+ if (!(intrinsics[Intrinsic_079] = CheckRuntimeObject("vec_mladd"))) return 0;
+ if (!(intrinsics[Intrinsic_080] = CheckRuntimeObject("vec_mradds"))) return 0;
+ if (!(intrinsics[Intrinsic_081] = CheckRuntimeObject("vec_msum"))) return 0;
+ if (!(intrinsics[Intrinsic_082] = CheckRuntimeObject("vec_msums"))) return 0;
+ if (!(intrinsics[Intrinsic_083] = CheckRuntimeObject("vec_mtvscr"))) return 0;
+ if (!(intrinsics[Intrinsic_084] = CheckRuntimeObject("vec_mule"))) return 0;
+ if (!(intrinsics[Intrinsic_085] = CheckRuntimeObject("vec_mulo"))) return 0;
+ if (!(intrinsics[Intrinsic_086] = CheckRuntimeObject("vec_nmsub"))) return 0;
+ if (!(intrinsics[Intrinsic_087] = CheckRuntimeObject("vec_nor"))) return 0;
+ if (!(intrinsics[Intrinsic_088] = CheckRuntimeObject("vec_or"))) return 0;
+ if (!(intrinsics[Intrinsic_089] = CheckRuntimeObject("vec_pack"))) return 0;
+ if (!(intrinsics[Intrinsic_090] = CheckRuntimeObject("vec_packpx"))) return 0;
+ if (!(intrinsics[Intrinsic_091] = CheckRuntimeObject("vec_packs"))) return 0;
+ if (!(intrinsics[Intrinsic_092] = CheckRuntimeObject("vec_packsu"))) return 0;
+ if (!(intrinsics[Intrinsic_093] = CheckRuntimeObject("vec_perm"))) return 0;
+ if (!(intrinsics[Intrinsic_094] = CheckRuntimeObject("vec_re"))) return 0;
+ if (!(intrinsics[Intrinsic_095] = CheckRuntimeObject("vec_rl"))) return 0;
+ if (!(intrinsics[Intrinsic_096] = CheckRuntimeObject("vec_round"))) return 0;
+ if (!(intrinsics[Intrinsic_097] = CheckRuntimeObject("vec_rsqrte"))) return 0;
+ if (!(intrinsics[Intrinsic_098] = CheckRuntimeObject("vec_sel"))) return 0;
+ if (!(intrinsics[Intrinsic_099] = CheckRuntimeObject("vec_sl"))) return 0;
+ if (!(intrinsics[Intrinsic_100] = CheckRuntimeObject("vec_sld"))) return 0;
+ if (!(intrinsics[Intrinsic_101] = CheckRuntimeObject("vec_sll"))) return 0;
+ if (!(intrinsics[Intrinsic_102] = CheckRuntimeObject("vec_slo"))) return 0;
+ if (!(intrinsics[Intrinsic_103] = CheckRuntimeObject("vec_splat"))) return 0;
+ if (!(intrinsics[Intrinsic_104] = CheckRuntimeObject("vec_splat_s8"))) return 0;
+ if (!(intrinsics[Intrinsic_105] = CheckRuntimeObject("vec_splat_s16"))) return 0;
+ if (!(intrinsics[Intrinsic_106] = CheckRuntimeObject("vec_splat_s32"))) return 0;
+ if (!(intrinsics[Intrinsic_107] = CheckRuntimeObject("vec_splat_u8"))) return 0;
+ if (!(intrinsics[Intrinsic_108] = CheckRuntimeObject("vec_splat_u16"))) return 0;
+ if (!(intrinsics[Intrinsic_109] = CheckRuntimeObject("vec_splat_u32"))) return 0;
+ if (!(intrinsics[Intrinsic_110] = CheckRuntimeObject("vec_sr"))) return 0;
+ if (!(intrinsics[Intrinsic_111] = CheckRuntimeObject("vec_sra"))) return 0;
+ if (!(intrinsics[Intrinsic_112] = CheckRuntimeObject("vec_srl"))) return 0;
+ if (!(intrinsics[Intrinsic_113] = CheckRuntimeObject("vec_sro"))) return 0;
+ if (!(intrinsics[Intrinsic_114] = CheckRuntimeObject("vec_st"))) return 0;
+ if (!(intrinsics[Intrinsic_115] = CheckRuntimeObject("vec_ste"))) return 0;
+ if (!(intrinsics[Intrinsic_116] = CheckRuntimeObject("vec_stl"))) return 0;
+ if (!(intrinsics[Intrinsic_117] = CheckRuntimeObject("vec_sub"))) return 0;
+ if (!(intrinsics[Intrinsic_118] = CheckRuntimeObject("vec_subc"))) return 0;
+ if (!(intrinsics[Intrinsic_119] = CheckRuntimeObject("vec_subs"))) return 0;
+ if (!(intrinsics[Intrinsic_120] = CheckRuntimeObject("vec_sum4s"))) return 0;
+ if (!(intrinsics[Intrinsic_121] = CheckRuntimeObject("vec_sum2s"))) return 0;
+ if (!(intrinsics[Intrinsic_122] = CheckRuntimeObject("vec_sums"))) return 0;
+ if (!(intrinsics[Intrinsic_123] = CheckRuntimeObject("vec_trunc"))) return 0;
+ if (!(intrinsics[Intrinsic_124] = CheckRuntimeObject("vec_unpack2sh"))) return 0;
+ if (!(intrinsics[Intrinsic_125] = CheckRuntimeObject("vec_unpack2sl"))) return 0;
+ if (!(intrinsics[Intrinsic_126] = CheckRuntimeObject("vec_unpack2uh"))) return 0;
+ if (!(intrinsics[Intrinsic_127] = CheckRuntimeObject("vec_unpack2ul"))) return 0;
+ if (!(intrinsics[Intrinsic_128] = CheckRuntimeObject("vec_unpackh"))) return 0;
+ if (!(intrinsics[Intrinsic_129] = CheckRuntimeObject("vec_unpackl"))) return 0;
+ if (!(intrinsics[Intrinsic_130] = CheckRuntimeObject("vec_xor"))) return 0;
+ if (!(intrinsics[Intrinsic_131] = CheckRuntimeObject("vec_all_eq"))) return 0;
+ if (!(intrinsics[Intrinsic_132] = CheckRuntimeObject("vec_all_ge"))) return 0;
+ if (!(intrinsics[Intrinsic_133] = CheckRuntimeObject("vec_all_gt"))) return 0;
+ if (!(intrinsics[Intrinsic_134] = CheckRuntimeObject("vec_all_in"))) return 0;
+ if (!(intrinsics[Intrinsic_135] = CheckRuntimeObject("vec_all_le"))) return 0;
+ if (!(intrinsics[Intrinsic_136] = CheckRuntimeObject("vec_all_lt"))) return 0;
+ if (!(intrinsics[Intrinsic_137] = CheckRuntimeObject("vec_all_nan"))) return 0;
+ if (!(intrinsics[Intrinsic_138] = CheckRuntimeObject("vec_all_ne"))) return 0;
+ if (!(intrinsics[Intrinsic_139] = CheckRuntimeObject("vec_all_nge"))) return 0;
+ if (!(intrinsics[Intrinsic_140] = CheckRuntimeObject("vec_all_ngt"))) return 0;
+ if (!(intrinsics[Intrinsic_141] = CheckRuntimeObject("vec_all_nle"))) return 0;
+ if (!(intrinsics[Intrinsic_142] = CheckRuntimeObject("vec_all_nlt"))) return 0;
+ if (!(intrinsics[Intrinsic_143] = CheckRuntimeObject("vec_all_numeric"))) return 0;
+ if (!(intrinsics[Intrinsic_144] = CheckRuntimeObject("vec_any_eq"))) return 0;
+ if (!(intrinsics[Intrinsic_145] = CheckRuntimeObject("vec_any_ge"))) return 0;
+ if (!(intrinsics[Intrinsic_146] = CheckRuntimeObject("vec_any_gt"))) return 0;
+ if (!(intrinsics[Intrinsic_147] = CheckRuntimeObject("vec_any_le"))) return 0;
+ if (!(intrinsics[Intrinsic_148] = CheckRuntimeObject("vec_any_lt"))) return 0;
+ if (!(intrinsics[Intrinsic_149] = CheckRuntimeObject("vec_any_nan"))) return 0;
+ if (!(intrinsics[Intrinsic_150] = CheckRuntimeObject("vec_any_ne"))) return 0;
+ if (!(intrinsics[Intrinsic_151] = CheckRuntimeObject("vec_any_nge"))) return 0;
+ if (!(intrinsics[Intrinsic_152] = CheckRuntimeObject("vec_any_ngt"))) return 0;
+ if (!(intrinsics[Intrinsic_153] = CheckRuntimeObject("vec_any_nle"))) return 0;
+ if (!(intrinsics[Intrinsic_154] = CheckRuntimeObject("vec_any_nlt"))) return 0;
+ if (!(intrinsics[Intrinsic_155] = CheckRuntimeObject("vec_any_numeric"))) return 0;
+ if (!(intrinsics[Intrinsic_156] = CheckRuntimeObject("vec_any_out"))) return 0;
+ if (!(intrinsics[Intrinsic_157] = CheckRuntimeObject("vec_vaddubm"))) return 0;
+ if (!(intrinsics[Intrinsic_158] = CheckRuntimeObject("vec_vadduhm"))) return 0;
+ if (!(intrinsics[Intrinsic_159] = CheckRuntimeObject("vec_vadduwm"))) return 0;
+ if (!(intrinsics[Intrinsic_160] = CheckRuntimeObject("vec_vaddfp"))) return 0;
+ if (!(intrinsics[Intrinsic_161] = CheckRuntimeObject("vec_vaddcuw"))) return 0;
+ if (!(intrinsics[Intrinsic_162] = CheckRuntimeObject("vec_vaddubs"))) return 0;
+ if (!(intrinsics[Intrinsic_163] = CheckRuntimeObject("vec_vaddubs"))) return 0;
+ if (!(intrinsics[Intrinsic_164] = CheckRuntimeObject("vec_vadduhs"))) return 0;
+ if (!(intrinsics[Intrinsic_165] = CheckRuntimeObject("vec_vadduhs"))) return 0;
+ if (!(intrinsics[Intrinsic_166] = CheckRuntimeObject("vec_vadduws"))) return 0;
+ if (!(intrinsics[Intrinsic_167] = CheckRuntimeObject("vec_vadduws"))) return 0;
+ if (!(intrinsics[Intrinsic_168] = CheckRuntimeObject("vec_vand"))) return 0;
+ if (!(intrinsics[Intrinsic_169] = CheckRuntimeObject("vec_vandc"))) return 0;
+ if (!(intrinsics[Intrinsic_170] = CheckRuntimeObject("vec_vavgub"))) return 0;
+ if (!(intrinsics[Intrinsic_171] = CheckRuntimeObject("vec_vavgsb"))) return 0;
+ if (!(intrinsics[Intrinsic_172] = CheckRuntimeObject("vec_vavguh"))) return 0;
+ if (!(intrinsics[Intrinsic_173] = CheckRuntimeObject("vec_vavgsh"))) return 0;
+ if (!(intrinsics[Intrinsic_174] = CheckRuntimeObject("vec_vavguw"))) return 0;
+ if (!(intrinsics[Intrinsic_175] = CheckRuntimeObject("vec_vavgsw"))) return 0;
+ if (!(intrinsics[Intrinsic_176] = CheckRuntimeObject("vec_vrfip"))) return 0;
+ if (!(intrinsics[Intrinsic_177] = CheckRuntimeObject("vec_vcmpbfp"))) return 0;
+ if (!(intrinsics[Intrinsic_178] = CheckRuntimeObject("vec_vcmpequb"))) return 0;
+ if (!(intrinsics[Intrinsic_179] = CheckRuntimeObject("vec_vcmpequh"))) return 0;
+ if (!(intrinsics[Intrinsic_180] = CheckRuntimeObject("vec_vcmpequw"))) return 0;
+ if (!(intrinsics[Intrinsic_181] = CheckRuntimeObject("vec_vcmpeqfp"))) return 0;
+ if (!(intrinsics[Intrinsic_182] = CheckRuntimeObject("vec_vcmpgefp"))) return 0;
+ if (!(intrinsics[Intrinsic_183] = CheckRuntimeObject("vec_vcmpgtub"))) return 0;
+ if (!(intrinsics[Intrinsic_184] = CheckRuntimeObject("vec_vcmpgtsb"))) return 0;
+ if (!(intrinsics[Intrinsic_185] = CheckRuntimeObject("vec_vcmpgtuh"))) return 0;
+ if (!(intrinsics[Intrinsic_186] = CheckRuntimeObject("vec_vcmpgtsh"))) return 0;
+ if (!(intrinsics[Intrinsic_187] = CheckRuntimeObject("vec_vcmpgtuw"))) return 0;
+ if (!(intrinsics[Intrinsic_188] = CheckRuntimeObject("vec_vcmpgtsw"))) return 0;
+ if (!(intrinsics[Intrinsic_189] = CheckRuntimeObject("vec_vcmpgtfp"))) return 0;
+ if (!(intrinsics[Intrinsic_190] = CheckRuntimeObject("vec_vcfux"))) return 0;
+ if (!(intrinsics[Intrinsic_191] = CheckRuntimeObject("vec_vcfsx"))) return 0;
+ if (!(intrinsics[Intrinsic_192] = CheckRuntimeObject("vec_vctsxs"))) return 0;
+ if (!(intrinsics[Intrinsic_193] = CheckRuntimeObject("vec_vctuxs"))) return 0;
+ if (!(intrinsics[Intrinsic_194] = CheckRuntimeObject("vec_vexptefp"))) return 0;
+ if (!(intrinsics[Intrinsic_195] = CheckRuntimeObject("vec_vrfim"))) return 0;
+ if (!(intrinsics[Intrinsic_196] = CheckRuntimeObject("vec_lvx"))) return 0;
+ if (!(intrinsics[Intrinsic_197] = CheckRuntimeObject("vec_lvebx"))) return 0;
+ if (!(intrinsics[Intrinsic_198] = CheckRuntimeObject("vec_lvehx"))) return 0;
+ if (!(intrinsics[Intrinsic_199] = CheckRuntimeObject("vec_lvewx"))) return 0;
+ if (!(intrinsics[Intrinsic_200] = CheckRuntimeObject("vec_lvxl"))) return 0;
+ if (!(intrinsics[Intrinsic_201] = CheckRuntimeObject("vec_vlogefp"))) return 0;
+ if (!(intrinsics[Intrinsic_202] = CheckRuntimeObject("vec_vmaddfp"))) return 0;
+ if (!(intrinsics[Intrinsic_203] = CheckRuntimeObject("vec_vmhaddshs"))) return 0;
+ if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vmaxub"))) return 0;
+ if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vmaxsb"))) return 0;
+ if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vmaxuh"))) return 0;
+ if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vmaxsh"))) return 0;
+ if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vmaxuw"))) return 0;
+ if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vmaxsw"))) return 0;
+ if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vmaxfp"))) return 0;
+ if (!(intrinsics[Intrinsic_211] = CheckRuntimeObject("vec_vmrghb"))) return 0;
+ if (!(intrinsics[Intrinsic_212] = CheckRuntimeObject("vec_vmrghh"))) return 0;
+ if (!(intrinsics[Intrinsic_213] = CheckRuntimeObject("vec_vmrghw"))) return 0;
+ if (!(intrinsics[Intrinsic_214] = CheckRuntimeObject("vec_vmrglb"))) return 0;
+ if (!(intrinsics[Intrinsic_215] = CheckRuntimeObject("vec_vmrglh"))) return 0;
+ if (!(intrinsics[Intrinsic_216] = CheckRuntimeObject("vec_vmrglw"))) return 0;
+ if (!(intrinsics[Intrinsic_204] = CheckRuntimeObject("vec_vminub"))) return 0;
+ if (!(intrinsics[Intrinsic_205] = CheckRuntimeObject("vec_vminsb"))) return 0;
+ if (!(intrinsics[Intrinsic_206] = CheckRuntimeObject("vec_vminuh"))) return 0;
+ if (!(intrinsics[Intrinsic_207] = CheckRuntimeObject("vec_vminsh"))) return 0;
+ if (!(intrinsics[Intrinsic_208] = CheckRuntimeObject("vec_vminuw"))) return 0;
+ if (!(intrinsics[Intrinsic_209] = CheckRuntimeObject("vec_vminsw"))) return 0;
+ if (!(intrinsics[Intrinsic_210] = CheckRuntimeObject("vec_vminfp"))) return 0;
+ if (!(intrinsics[Intrinsic_224] = CheckRuntimeObject("vec_vmladduhm"))) return 0;
+ if (!(intrinsics[Intrinsic_225] = CheckRuntimeObject("vec_vmhraddshs"))) return 0;
+ if (!(intrinsics[Intrinsic_226] = CheckRuntimeObject("vec_vmsumubm"))) return 0;
+ if (!(intrinsics[Intrinsic_227] = CheckRuntimeObject("vec_vmsumuhm"))) return 0;
+ if (!(intrinsics[Intrinsic_228] = CheckRuntimeObject("vec_vmsummbm"))) return 0;
+ if (!(intrinsics[Intrinsic_229] = CheckRuntimeObject("vec_vmsumshm"))) return 0;
+ if (!(intrinsics[Intrinsic_230] = CheckRuntimeObject("vec_vmsumuhs"))) return 0;
+ if (!(intrinsics[Intrinsic_231] = CheckRuntimeObject("vec_vmsumshs"))) return 0;
+ if (!(intrinsics[Intrinsic_232] = CheckRuntimeObject("vec_vmuleub"))) return 0;
+ if (!(intrinsics[Intrinsic_233] = CheckRuntimeObject("vec_vmulesb"))) return 0;
+ if (!(intrinsics[Intrinsic_234] = CheckRuntimeObject("vec_vmuleuh"))) return 0;
+ if (!(intrinsics[Intrinsic_235] = CheckRuntimeObject("vec_vmulesh"))) return 0;
+ if (!(intrinsics[Intrinsic_236] = CheckRuntimeObject("vec_vmuloub"))) return 0;
+ if (!(intrinsics[Intrinsic_237] = CheckRuntimeObject("vec_vmulosb"))) return 0;
+ if (!(intrinsics[Intrinsic_238] = CheckRuntimeObject("vec_vmulouh"))) return 0;
+ if (!(intrinsics[Intrinsic_239] = CheckRuntimeObject("vec_vmulosh"))) return 0;
+ if (!(intrinsics[Intrinsic_240] = CheckRuntimeObject("vec_vnmsubfp"))) return 0;
+ if (!(intrinsics[Intrinsic_241] = CheckRuntimeObject("vec_vnor"))) return 0;
+ if (!(intrinsics[Intrinsic_242] = CheckRuntimeObject("vec_vor"))) return 0;
+ if (!(intrinsics[Intrinsic_243] = CheckRuntimeObject("vec_vpkuhum"))) return 0;
+ if (!(intrinsics[Intrinsic_244] = CheckRuntimeObject("vec_vpkuwum"))) return 0;
+ if (!(intrinsics[Intrinsic_245] = CheckRuntimeObject("vec_vpkpx"))) return 0;
+ if (!(intrinsics[Intrinsic_246] = CheckRuntimeObject("vec_vpkuhus"))) return 0;
+ if (!(intrinsics[Intrinsic_247] = CheckRuntimeObject("vec_vpkshss"))) return 0;
+ if (!(intrinsics[Intrinsic_248] = CheckRuntimeObject("vec_vpkuwus"))) return 0;
+ if (!(intrinsics[Intrinsic_249] = CheckRuntimeObject("vec_vpkswss"))) return 0;
+ if (!(intrinsics[Intrinsic_250] = CheckRuntimeObject("vec_vpkshus"))) return 0;
+ if (!(intrinsics[Intrinsic_251] = CheckRuntimeObject("vec_vpkswus"))) return 0;
+ if (!(intrinsics[Intrinsic_252] = CheckRuntimeObject("vec_vperm"))) return 0;
+ if (!(intrinsics[Intrinsic_253] = CheckRuntimeObject("vec_vrefp"))) return 0;
+ if (!(intrinsics[Intrinsic_254] = CheckRuntimeObject("vec_vrlb"))) return 0;
+ if (!(intrinsics[Intrinsic_255] = CheckRuntimeObject("vec_vrlh"))) return 0;
+ if (!(intrinsics[Intrinsic_256] = CheckRuntimeObject("vec_vrlw"))) return 0;
+ if (!(intrinsics[Intrinsic_257] = CheckRuntimeObject("vec_vrfin"))) return 0;
+ if (!(intrinsics[Intrinsic_258] = CheckRuntimeObject("vec_vrsqrtefp"))) return 0;
+ if (!(intrinsics[Intrinsic_259] = CheckRuntimeObject("vec_vsel"))) return 0;
+ if (!(intrinsics[Intrinsic_260] = CheckRuntimeObject("vec_vslb"))) return 0;
+ if (!(intrinsics[Intrinsic_261] = CheckRuntimeObject("vec_vslh"))) return 0;
+ if (!(intrinsics[Intrinsic_262] = CheckRuntimeObject("vec_vslw"))) return 0;
+ if (!(intrinsics[Intrinsic_263] = CheckRuntimeObject("vec_vsldoi"))) return 0;
+ if (!(intrinsics[Intrinsic_264] = CheckRuntimeObject("vec_vsl"))) return 0;
+ if (!(intrinsics[Intrinsic_265] = CheckRuntimeObject("vec_vslo"))) return 0;
+ if (!(intrinsics[Intrinsic_266] = CheckRuntimeObject("vec_vspltb"))) return 0;
+ if (!(intrinsics[Intrinsic_267] = CheckRuntimeObject("vec_vsplth"))) return 0;
+ if (!(intrinsics[Intrinsic_268] = CheckRuntimeObject("vec_vspltw"))) return 0;
+ if (!(intrinsics[Intrinsic_269] = CheckRuntimeObject("vec_vspltisb"))) return 0;
+ if (!(intrinsics[Intrinsic_270] = CheckRuntimeObject("vec_vspltish"))) return 0;
+ if (!(intrinsics[Intrinsic_271] = CheckRuntimeObject("vec_vspltisw"))) return 0;
+ if (!(intrinsics[Intrinsic_272] = CheckRuntimeObject("vec_vsrb"))) return 0;
+ if (!(intrinsics[Intrinsic_273] = CheckRuntimeObject("vec_vsrh"))) return 0;
+ if (!(intrinsics[Intrinsic_274] = CheckRuntimeObject("vec_vsrw"))) return 0;
+ if (!(intrinsics[Intrinsic_275] = CheckRuntimeObject("vec_vsrab"))) return 0;
+ if (!(intrinsics[Intrinsic_276] = CheckRuntimeObject("vec_vsrah"))) return 0;
+ if (!(intrinsics[Intrinsic_277] = CheckRuntimeObject("vec_vsraw"))) return 0;
+ if (!(intrinsics[Intrinsic_278] = CheckRuntimeObject("vec_vsr"))) return 0;
+ if (!(intrinsics[Intrinsic_279] = CheckRuntimeObject("vec_vsro"))) return 0;
+ if (!(intrinsics[Intrinsic_280] = CheckRuntimeObject("vec_stvx"))) return 0;
+ if (!(intrinsics[Intrinsic_281] = CheckRuntimeObject("vec_stvebx"))) return 0;
+ if (!(intrinsics[Intrinsic_282] = CheckRuntimeObject("vec_stvehx"))) return 0;
+ if (!(intrinsics[Intrinsic_283] = CheckRuntimeObject("vec_stvewx"))) return 0;
+ if (!(intrinsics[Intrinsic_284] = CheckRuntimeObject("vec_stvxl"))) return 0;
+ if (!(intrinsics[Intrinsic_285] = CheckRuntimeObject("vec_vsububm"))) return 0;
+ if (!(intrinsics[Intrinsic_286] = CheckRuntimeObject("vec_vsubuhm"))) return 0;
+ if (!(intrinsics[Intrinsic_287] = CheckRuntimeObject("vec_vsubuwm"))) return 0;
+ if (!(intrinsics[Intrinsic_288] = CheckRuntimeObject("vec_vsubfp"))) return 0;
+ if (!(intrinsics[Intrinsic_289] = CheckRuntimeObject("vec_vsubcuw"))) return 0;
+ if (!(intrinsics[Intrinsic_290] = CheckRuntimeObject("vec_vsububs"))) return 0;
+ if (!(intrinsics[Intrinsic_291] = CheckRuntimeObject("vec_vsubsbs"))) return 0;
+ if (!(intrinsics[Intrinsic_292] = CheckRuntimeObject("vec_vsubuhs"))) return 0;
+ if (!(intrinsics[Intrinsic_293] = CheckRuntimeObject("vec_vsubshs"))) return 0;
+ if (!(intrinsics[Intrinsic_294] = CheckRuntimeObject("vec_vsubuws"))) return 0;
+ if (!(intrinsics[Intrinsic_295] = CheckRuntimeObject("vec_vsubsws"))) return 0;
+ if (!(intrinsics[Intrinsic_296] = CheckRuntimeObject("vec_vsum4ubs"))) return 0;
+ if (!(intrinsics[Intrinsic_297] = CheckRuntimeObject("vec_vsum4sbs"))) return 0;
+ if (!(intrinsics[Intrinsic_298] = CheckRuntimeObject("vec_vsum4shs"))) return 0;
+ if (!(intrinsics[Intrinsic_299] = CheckRuntimeObject("vec_vsum2sws"))) return 0;
+ if (!(intrinsics[Intrinsic_300] = CheckRuntimeObject("vec_vsumsws"))) return 0;
+ if (!(intrinsics[Intrinsic_301] = CheckRuntimeObject("vec_vrfiz"))) return 0;
+ if (!(intrinsics[Intrinsic_302] = CheckRuntimeObject("vec_vupkhsb"))) return 0;
+ if (!(intrinsics[Intrinsic_303] = CheckRuntimeObject("vec_vupklsb"))) return 0;
+ if (!(intrinsics[Intrinsic_304] = CheckRuntimeObject("vec_vupkhpx"))) return 0;
+ if (!(intrinsics[Intrinsic_305] = CheckRuntimeObject("vec_vupklpx"))) return 0;
+ if (!(intrinsics[Intrinsic_306] = CheckRuntimeObject("vec_vupkhsh"))) return 0;
+ if (!(intrinsics[Intrinsic_307] = CheckRuntimeObject("vec_vupklsh"))) return 0;
+ if (!(intrinsics[Intrinsic_308] = CheckRuntimeObject("vec_vxor"))) return 0;
+ if (!(intrinsics[Intrinsic_309] = CheckRuntimeObject("vec_abs"))) return 0;
+ if (!(intrinsics[Intrinsic_310] = CheckRuntimeObject("vec_abss"))) return 0;
+ }
+
+ return 1;
+}
+
+Boolean Intrinsics_IsPublicRuntimeObject(Object *object) {
+ int i;
+
+ for (i = 0; i < MaxIntrinsics; i++) {
+ if (object == intrinsics[i])
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c
new file mode 100644
index 0000000..c5da285
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Operands.c
@@ -0,0 +1,1040 @@
+#include "compiler/Operands.h"
+#include "compiler/CError.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/Registers.h"
+#include "compiler/StackFrame.h"
+#include "compiler/TOC.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+
+unsigned long long uns_to_float_cc = 0x4330000000000000;
+unsigned long long int_to_float_cc = 0x4330000080000000;
+Float one_point_zero = {1.0};
+
+void load_immediate(short reg, SInt32 value) {
+ short tmpreg = reg;
+ short tmpreg2;
+
+ if (!FITS_IN_SHORT(value)) {
+ if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(value))
+ tmpreg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmpreg2 = tmpreg, 0, (short) HIGH_PART(value));
+ if (LOW_PART_BUGGY(value))
+ emitpcode(PC_ADDI, reg, tmpreg2, 0, LOW_PART(value));
+ } else {
+ emitpcode(PC_LI, reg, value);
+ }
+}
+
+static void set_op_flags(Operand *op, ENode *expr) {
+ CError_ASSERT(118, op);
+
+ if (expr) {
+ if (expr->type == EINTCONST) {
+ op->flags = 0;
+ if (expr->flags & ENODE_FLAG_VOLATILE)
+ op->flags |= OpndFlags_Volatile;
+ if (expr->flags & ENODE_FLAG_CONST)
+ op->flags |= OpndFlags_Const;
+ } else {
+ op->flags = CParserIsVolatileExpr(expr) ? OpndFlags_Volatile : 0;
+ op->flags |= CParserIsConstExpr(expr) ? OpndFlags_Const : 0;
+ }
+ } else {
+ op->flags = 0;
+ }
+}
+
+void symbol_operand(Operand *op, Object *obj) {
+ memclrw(op, sizeof(Operand));
+ op->optype = OpndType_Symbol;
+ op->object = obj;
+}
+
+void indirect(Operand *op, ENode *expr) {
+ switch (op->optype) {
+ case OpndType_GPRPair:
+ CError_FATAL(163);
+ case OpndType_CRField:
+ case OpndType_IndirectGPR_ImmOffset:
+ case OpndType_IndirectGPR_Indexed:
+ case OpndType_IndirectSymbol:
+ if (op->optype)
+ Coerce_to_register(op, TYPE(&void_ptr), 0);
+ case OpndType_GPR:
+ op->immOffset = 0;
+ op->object = NULL;
+ case OpndType_GPR_ImmOffset:
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_GPR_Indexed:
+ op->optype = OpndType_IndirectGPR_Indexed;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_Absolute:
+ if (FITS_IN_SHORT(op->immediate)) {
+ op->reg = 0;
+ op->immOffset = op->immediate;
+ } else {
+ emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->immediate));
+ op->immOffset = LOW_PART(op->immediate);
+ }
+ op->object = NULL;
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ set_op_flags(op, expr);
+ break;
+ case OpndType_Symbol:
+ op->optype = OpndType_IndirectSymbol;
+ set_op_flags(op, expr);
+ break;
+ default:
+ CError_FATAL(215);
+ }
+}
+
+#define COMBO_OP(a, b) (b + (a * 11))
+
+void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
+ Operand *tmp_op;
+ int tmp;
+
+ if (opA->optype == OpndType_Symbol || opA->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opA);
+ if (opB->optype == OpndType_Symbol || opB->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opB);
+
+ switch (COMBO_OP(opA->optype, opB->optype)) {
+ case COMBO_OP(OpndType_GPR, OpndType_GPR):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = opB->reg;
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_ImmOffset):
+ if (FITS_IN_SHORT(opA->immOffset + opB->immOffset) && (!opA->object || !opB->object)) {
+ opB->immOffset += opA->immOffset;
+ if (!opB->object)
+ opB->object = opA->object;
+ } else {
+ tmp = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(tmp, opA->reg, opA->object, opA->immOffset);
+ opA->reg = tmp;
+ }
+ case COMBO_OP(OpndType_GPR, OpndType_GPR_ImmOffset):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR):
+ if (opA->reg == _FP_ || opA->reg == _CALLER_SP_) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opB->reg;
+ add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
+ } else if (opB->reg == _FP_ || opB->reg == _CALLER_SP_) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opA->reg;
+ add_immediate(opOut->reg, opB->reg, opA->object, LOW_PART(opA->immOffset));
+ } else if (opA->object) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = opB->reg;
+ add_immediate(opOut->reg, opA->reg, opA->object, LOW_PART(opA->immOffset));
+ } else {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opOut->immOffset = opA->immOffset;
+ opOut->object = opA->object;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opB->reg);
+ }
+ break;
+ case COMBO_OP(OpndType_GPR, OpndType_GPR_Indexed):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = (output_reg && (output_reg != opA->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->regOffset, opA->regOffset, opB->reg);
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_GPR_Indexed):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_ImmOffset):
+ if (opB->object) {
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ opOut->regOffset = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
+ add_immediate(opOut->regOffset, opB->reg, opB->object, opB->immOffset);
+ } else {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->immOffset = opB->immOffset;
+ opOut->object = opB->object;
+ opOut->reg = (output_reg && (output_reg != opB->reg)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->reg, opA->reg, opA->regOffset);
+ emitpcode(PC_ADD, opOut->reg, opOut->reg, opB->reg);
+ }
+ break;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_GPR_Indexed):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opA->reg;
+ opOut->regOffset = (output_reg && (output_reg != opA->regOffset)) ? output_reg
+ : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, opOut->regOffset, opB->reg, opB->regOffset);
+ emitpcode(PC_ADD, opOut->regOffset, opOut->regOffset, opA->regOffset);
+ break;
+ case COMBO_OP(OpndType_GPR_ImmOffset, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR_ImmOffset):
+ if (!opB->object) {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->reg = opB->reg;
+ opOut->immOffset = opB->immOffset;
+ opOut->object = opB->object;
+ if (FITS_IN_SHORT(opOut->immOffset + opA->immediate)) {
+ opOut->immOffset += opA->immediate;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (!HIGH_PART(opA->immediate)) {
+ emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->immediate));
+ } else {
+ emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate));
+ if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->immediate))) {
+ opOut->immOffset += LOW_PART(opA->immediate);
+ } else {
+ emitpcode(PC_ADDI, opOut->reg, opOut->reg, 0, LOW_PART(opA->immediate));
+ }
+ }
+ }
+ break;
+ } else if (opB->object->datatype == DLOCAL && can_add_displ_to_local(opB->object, opB->immOffset + opA->immediate)) {
+ opOut->optype = OpndType_GPR_ImmOffset;
+ opOut->object = opB->object;
+ opOut->reg = opB->reg;
+ opOut->immOffset = LOW_PART(opB->immOffset + opA->immediate);
+ break;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(opOut->reg, opB->reg, opB->object, opB->immOffset);
+ opB->optype = OpndType_GPR;
+ opB->reg = opOut->reg;
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ }
+ case COMBO_OP(OpndType_GPR, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR):
+ opOut->optype = (opA->immediate != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR;
+ opOut->immOffset = LOW_PART(opA->immediate);
+ opOut->object = NULL;
+ if (FITS_IN_SHORT(opA->immediate)) {
+ opOut->reg = opB->reg;
+ } else {
+ opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate));
+ }
+ break;
+ case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute):
+ tmp_op = opA;
+ opA = opB;
+ opB = tmp_op;
+ case COMBO_OP(OpndType_Absolute, OpndType_GPR_Indexed):
+ opOut->optype = OpndType_GPR_Indexed;
+ opOut->reg = opB->reg;
+ opOut->regOffset = (output_reg && (output_reg != opB->reg)) ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (!HIGH_PART(opA->immediate)) {
+ emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->immediate));
+ } else {
+ emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->immediate));
+ if (LOW_PART_BUGGY(opA->immediate))
+ emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->immediate));
+ }
+ break;
+ case COMBO_OP(OpndType_Absolute, OpndType_Absolute):
+ opOut->optype = OpndType_Absolute;
+ opOut->immediate = opA->immediate + opB->immediate;
+ break;
+ default:
+ CError_FATAL(415);
+ }
+}
+
+void coerce_to_addressable(Operand *op) {
+ UInt32 offset;
+ short reg;
+ short flag;
+ short tmp;
+ Object *obj;
+
+ flag = 0;
+ obj = op->object;
+ tmp = 0;
+
+ switch (op->optype) {
+ case OpndType_GPR:
+ case OpndType_GPR_ImmOffset:
+ case OpndType_GPR_Indexed:
+ case OpndType_GPRPair:
+ case OpndType_Absolute:
+ case OpndType_VR:
+ case OpndType_CRField:
+ case OpndType_IndirectGPR_ImmOffset:
+ case OpndType_IndirectGPR_Indexed:
+ break;
+ case OpndType_IndirectSymbol:
+ flag = 1;
+ case OpndType_Symbol:
+ if (obj->datatype == DLOCAL) {
+ if (!local_is_16bit_offset(obj)) {
+ reg = used_virtual_registers[RegClass_GPR]++;
+ op_absolute_ha(reg, local_base_register(obj), obj, 0, 1);
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = reg;
+ op->object = obj;
+ } else {
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = local_base_register(obj);
+ op->object = obj;
+ }
+ } else if (obj->datatype == DABSOLUTE) {
+ offset = obj->u.address;
+ if (FITS_IN_SHORT(offset)) {
+ op->reg = 0;
+ op->immOffset = obj->u.address;
+ } else {
+ emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(offset));
+ op->immOffset = LOW_PART(obj->u.address);
+ }
+ op->object = obj;
+ op->optype = OpndType_GPR_ImmOffset;
+ } else {
+ if (copts.codegen_pic)
+ tmp = pic_base_reg;
+ reg = used_virtual_registers[RegClass_GPR]++;
+ op_absolute_ha(reg, tmp, obj, 0, 1);
+ op->optype = OpndType_GPR_ImmOffset;
+ op->reg = reg;
+ }
+ if (flag) {
+ if (op->optype == OpndType_GPR_ImmOffset) {
+ op->optype = OpndType_IndirectGPR_ImmOffset;
+ } else {
+ CError_FATAL(563);
+ }
+ }
+ break;
+ default:
+ CError_FATAL(581);
+ }
+}
+
+void Coerce_to_register(Operand *op, Type *type, short output_reg) {
+ SInt32 offset;
+ Opcode opcode;
+ short reg;
+ short tmp;
+ short cond_neg;
+ short cond;
+ short bit_offset;
+ short bit_size;
+
+ if (TYPE_IS_8BYTES(type)) {
+ coerce_to_register_pair(op, type, output_reg, 0);
+ return;
+ }
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_GPRPair:
+ return;
+ case OpndType_GPR:
+ return;
+ case OpndType_GPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(reg, op->reg, op->object, op->immOffset);
+ break;
+ case OpndType_GPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, reg, op->reg, op->regOffset);
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ offset = op->immediate;
+ if (FITS_IN_SHORT(offset)) {
+ emitpcode(PC_LI, reg, offset);
+ } else {
+ tmp = reg;
+ if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset))
+ tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmp, 0, (short) HIGH_PART(offset));
+ if (LOW_PART_BUGGY(offset))
+ emitpcode(PC_ADDI, reg, tmp, 0, LOW_PART(offset));
+ }
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opcode = PC_LWZ;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_LBZ;
+ break;
+ case 2:
+ if (is_unsigned(type))
+ opcode = PC_LHZ;
+ else
+ opcode = PC_LHA;
+ break;
+ }
+ } else {
+ CError_ASSERT(680, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ opcode = PC_LWZX;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_LBZX;
+ break;
+ case 2:
+ if (is_unsigned(type))
+ opcode = PC_LHZX;
+ else
+ opcode = PC_LHAX;
+ break;
+ }
+ } else {
+ CError_ASSERT(724, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ emitpcode(opcode, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_CRField:
+ cond_neg = 0;
+ cond = 0;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MFCR, tmp = reg);
+ switch (op->regOffset) {
+ case ENOTEQU:
+ cond_neg = 1;
+ case EEQU:
+ cond = 2;
+ break;
+ case EGREATEREQU:
+ cond_neg = 1;
+ case ELESS:
+ cond = 0;
+ break;
+ case ELESSEQU:
+ cond_neg = 1;
+ case EGREATER:
+ cond = 1;
+ break;
+ default:
+ CError_FATAL(758);
+ }
+ bit_offset = cond + (op->reg << 2);
+ bit_size = 1;
+ emitpcode(PC_RLWINM, tmp, tmp, (bit_size + bit_offset) & 31, 32 - bit_size, 31);
+ if (cond_neg)
+ emitpcode(PC_XORI, tmp, tmp, 1);
+ break;
+ default:
+ CError_FATAL(769);
+ }
+
+ op->optype = OpndType_GPR;
+ op->reg = reg;
+}
+
+void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short output_regHi) {
+ SInt32 offset;
+ short reg;
+ short regHi;
+ short tmp1;
+ short tmp2;
+
+ regHi = -1;
+
+ CError_ASSERT(794, TYPE_IS_8BYTES(type) || (IS_TYPE_STRUCT(type) && type->size == 8));
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_GPRPair:
+ if (output_reg && !output_regHi)
+ output_regHi = used_virtual_registers[RegClass_GPR]++;
+ if (output_regHi && !output_reg)
+ output_reg = used_virtual_registers[RegClass_GPR]++;
+ if (op->reg != output_reg || op->regHi != output_regHi) {
+ tmp1 = output_reg ? output_reg : op->reg;
+ tmp2 = output_regHi ? output_regHi : op->regHi;
+ if (tmp1 != op->reg) {
+ if (tmp1 == op->regHi) {
+ CError_ASSERT(818, tmp1 != tmp2);
+ emitpcode(PC_MR, tmp2, op->regHi);
+ emitpcode(PC_MR, tmp1, op->reg);
+ } else {
+ emitpcode(PC_MR, tmp1, op->reg);
+ if (op->regHi != tmp2)
+ emitpcode(PC_MR, tmp2, op->regHi);
+ }
+ } else if (tmp2 != op->regHi) {
+ if (tmp2 == op->reg) {
+ CError_ASSERT(832, tmp1 != tmp2);
+ emitpcode(PC_MR, tmp1, op->reg);
+ emitpcode(PC_MR, tmp2, op->regHi);
+ } else {
+ emitpcode(PC_MR, tmp2, op->regHi);
+ if (op->reg != tmp1)
+ emitpcode(PC_MR, tmp1, op->reg);
+ }
+ }
+ }
+ reg = op->reg;
+ regHi = op->regHi;
+ break;
+ case OpndType_GPR:
+ CError_FATAL(849);
+ break;
+ case OpndType_GPR_ImmOffset:
+ CError_FATAL(852);
+ break;
+ case OpndType_GPR_Indexed:
+ CError_FATAL(855);
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ offset = op->immediate;
+ if (FITS_IN_SHORT(offset)) {
+ emitpcode(PC_LI, reg, offset);
+ } else {
+ tmp1 = reg;
+ if (copts.optimizationlevel > 1 && LOW_PART_BUGGY(offset))
+ tmp1 = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmp1, 0, (short) HIGH_PART(offset));
+ if (LOW_PART_BUGGY(offset))
+ emitpcode(PC_ADDI, reg, tmp1, 0, LOW_PART(offset));
+ }
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (is_unsigned(type) || offset >= 0)
+ load_immediate(regHi, 0);
+ else
+ load_immediate(regHi, -1);
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (op->reg == regHi) {
+ if (op->reg == reg) {
+ CError_FATAL(887);
+ } else {
+ load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ }
+ } else {
+ load_store_register(PC_LWZ, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ }
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, reg, op->reg, op->regOffset);
+ load_store_register(PC_LWZ, regHi, reg, NULL, high_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_LWZ, reg, reg, NULL, low_offset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(912);
+ }
+
+ if (regHi == -1) {
+ CError_FATAL(916);
+ } else {
+ op->optype = OpndType_GPRPair;
+ op->reg = reg;
+ op->regHi = regHi;
+ }
+}
+
+void Coerce_to_fp_register(Operand *op, Type *type, short output_reg) {
+ short reg;
+
+ coerce_to_addressable(op);
+
+ switch (op->optype) {
+ case OpndType_FPR:
+ reg = op->reg;
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ load_store_register((type->size == 4) ? PC_LFS : PC_LFD, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ emitpcode((type->size == 4) ? PC_LFSX : PC_LFDX, reg, op->reg, op->regOffset, 0, 0x390);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(986);
+ }
+
+ op->optype = OpndType_FPR;
+ op->reg = reg;
+}
+
+void Coerce_to_v_register(Operand *op, Type *type, short output_reg) {
+ short reg;
+
+ coerce_to_addressable(op);
+
+ switch (op->optype) {
+ case OpndType_VR:
+ reg = op->reg;
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ load_store_register(PC_LVX, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ emitpcode(PC_LVX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_Absolute:
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_VR]++;
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_VECTOR_UCHAR:
+ case STRUCT_VECTOR_SCHAR:
+ case STRUCT_VECTOR_BCHAR:
+ emitpcode(PC_VSPLTISB, reg, op->immediate);
+ break;
+ case STRUCT_VECTOR_USHORT:
+ case STRUCT_VECTOR_SSHORT:
+ case STRUCT_VECTOR_BSHORT:
+ case STRUCT_VECTOR_PIXEL:
+ emitpcode(PC_VSPLTISH, reg, op->immediate);
+ break;
+ case STRUCT_VECTOR_UINT:
+ case STRUCT_VECTOR_SINT:
+ case STRUCT_VECTOR_BINT:
+ case STRUCT_VECTOR_FLOAT:
+ emitpcode(PC_VSPLTISW, reg, op->immediate);
+ break;
+ default:
+ CError_FATAL(1049);
+ }
+ op->optype = OpndType_VR;
+ op->reg = reg;
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(1059);
+ }
+
+ op->optype = OpndType_VR;
+ op->reg = reg;
+}
+
+void store(short reg, Operand *op, Type *type) {
+ Opcode opcode;
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ opcode = PC_STW;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_STB;
+ break;
+ case 2:
+ opcode = PC_STH;
+ break;
+ }
+ } else {
+ CError_ASSERT(1171, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ load_store_register(opcode, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ opcode = PC_STWX;
+ if (IS_TYPE_INT(type) || IS_TYPE_ENUM(type)) {
+ switch (type->size) {
+ case 1:
+ opcode = PC_STBX;
+ break;
+ case 2:
+ opcode = PC_STHX;
+ break;
+ }
+ } else {
+ CError_ASSERT(1188, IS_TYPE_POINTER(type) || IS_TYPE_4BYTES_MEMBERPOINTER(type));
+ }
+ emitpcode(opcode, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(1193);
+ }
+}
+
+void store_pair(short reg, short regHi, Operand *op, Type *type) {
+ short tmp;
+
+ CError_ASSERT(1208, TYPE_IS_8BYTES(type));
+
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register(PC_STW, reg, op->reg, op->object, op->immOffset + low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_STW, regHi, op->reg, op->object, op->immOffset + high_offset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, tmp, op->reg, op->regOffset);
+ load_store_register(PC_STW, reg, tmp, NULL, low_offset);
+ setpcodeflags(op->flags);
+ load_store_register(PC_STW, regHi, tmp, NULL, high_offset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(1228);
+ }
+}
+
+void store_fp(short reg, Operand *op, Type *type) {
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register((type->size == 4) ? PC_STFS : PC_STFD, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ emitpcode((type->size == 4) ? PC_STFSX : PC_STFDX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(1259);
+ }
+}
+
+void store_v(short reg, Operand *op, Type *tstruct) {
+ coerce_to_addressable(op);
+ switch (op->optype) {
+ case OpndType_IndirectGPR_ImmOffset:
+ load_store_register(PC_STVX, reg, op->reg, op->object, op->immOffset);
+ setpcodeflags(op->flags);
+ break;
+ case OpndType_IndirectGPR_Indexed:
+ emitpcode(PC_STVX, reg, op->reg, op->regOffset);
+ setpcodeflags(op->flags);
+ break;
+ default:
+ CError_FATAL(1283);
+ }
+}
+
+static Boolean last_matches_rlwinm_or_exts(Operand *op, short opcode, short b, short c) {
+ PCode *pc;
+
+ if (pclastblock->pcodeCount <= 0)
+ return 0;
+
+ pc = pclastblock->lastPCode;
+ if (pc->args[0].kind != PCOp_REGISTER || pc->args[0].arg != RegClass_GPR || pc->args[0].data.reg.reg != op->reg)
+ return 0;
+
+ if (pc->op != opcode && (opcode != PC_EXTSH || pc->op != PC_EXTSB))
+ return 0;
+
+ if (opcode == PC_RLWINM) {
+ if (pc->args[2].data.imm.value != 0 || pc->args[3].data.imm.value != b || pc->args[4].data.imm.value != c)
+ return 0;
+ }
+
+ return 1;
+}
+
+void extend32(Operand *op, Type *type, short output_reg) {
+ int r28;
+ int reg;
+
+ r28 = op->optype >= OpndType_IndirectGPR_ImmOffset;
+ if (op->optype != OpndType_GPR)
+ Coerce_to_register(op, type, output_reg);
+
+ switch (type->size) {
+ case 1:
+ if (is_unsigned(type)) {
+ if (r28)
+ return;
+ if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 24, 31))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, reg, op->reg, 0, 24, 31);
+ } else {
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ if (last_matches_rlwinm_or_exts(op, PC_EXTSB, 0, 0))
+ return;
+ emitpcode(PC_EXTSB, reg, op->reg);
+ }
+ break;
+ case 2:
+ if (r28)
+ return;
+ if (is_unsigned(type)) {
+ if (last_matches_rlwinm_or_exts(op, PC_RLWINM, 16, 31))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, reg, op->reg, 0, 16, 31);
+ } else {
+ if (last_matches_rlwinm_or_exts(op, PC_EXTSH, 0, 0))
+ return;
+ reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_EXTSH, reg, op->reg);
+ }
+ break;
+ default:
+ CError_FATAL(1389);
+ }
+
+ op->optype = OpndType_GPR;
+ op->reg = reg;
+}
+
+void extend64(Operand *op, Type *type, short output_reg, short output_regHi) {
+ short tmp;
+ short regHi;
+
+ if (op->optype != OpndType_GPR)
+ Coerce_to_register(op, type, output_reg);
+
+ regHi = output_regHi ? output_regHi : used_virtual_registers[RegClass_GPR]++;
+ if (regHi == op->reg) {
+ tmp = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, tmp, op->reg);
+ op->reg = tmp;
+ }
+
+ if (is_unsigned(type))
+ load_immediate(regHi, 0);
+ else
+ emitpcode(PC_SRAWI, regHi, op->reg, 31);
+
+ op->optype = OpndType_GPRPair;
+ op->regHi = regHi;
+}
+
+void load_floating_constant(short reg, Type *type, Float *data) {
+ Object *object;
+ Object *indObject;
+ Operand op1;
+ Operand op2;
+ Operand op3;
+ SInt32 offset = 0;
+
+ memclrw(&op1, sizeof(Operand));
+
+ object = CreateFloatConst(type, data, &offset);
+ indObject = createIndirect(object, 0, 1);
+
+ if (indObject) {
+ symbol_operand(&op1, indObject);
+ indirect(&op1, NULL);
+ } else {
+ symbol_operand(&op1, object);
+ }
+
+ if (offset) {
+ op2 = op1;
+ memclrw(&op3, sizeof(Operand));
+ op3.optype = OpndType_Absolute;
+ op3.immediate = offset;
+ if (op2.optype != OpndType_GPR)
+ Coerce_to_register(&op2, TYPE(&void_ptr), 0);
+ combine(&op2, &op3, 0, &op1);
+ }
+
+ indirect(&op1, NULL);
+ if (op1.optype != OpndType_FPR)
+ Coerce_to_fp_register(&op1, type, reg);
+}
+
+void convert_integer_to_floating(Operand *op, Boolean is_single, short output_reg) {
+ Operand temp_op;
+ Float d;
+ int const_reg;
+ int tmp_reg;
+ int work_reg;
+ int result_reg;
+ Opcode opcode;
+
+ symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
+ coerce_to_addressable(&temp_op);
+ d.value = *((double *) &int_to_float_cc);
+
+ const_reg = used_virtual_registers[RegClass_FPR]++;
+ load_floating_constant(const_reg, TYPE(&stdouble), &d);
+
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_XORIS, tmp_reg, op->reg, 0x8000);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, low_offset);
+
+ emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
+
+ load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ if (is_single != 0)
+ opcode = PC_FSUBS;
+ else
+ opcode = PC_FSUB;
+ emitpcode(opcode, result_reg, work_reg, const_reg);
+
+ op->optype = OpndType_FPR;
+ op->reg = result_reg;
+}
+
+void convert_unsigned_to_floating(Operand *op, Boolean is_single, short output_reg) {
+ Operand temp_op;
+ Float d;
+ int const_reg;
+ int tmp_reg;
+ int work_reg;
+ int result_reg;
+ Opcode opcode;
+
+ symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
+ coerce_to_addressable(&temp_op);
+ d.value = *((double *) &uns_to_float_cc);
+
+ const_reg = used_virtual_registers[RegClass_FPR]++;
+ load_floating_constant(const_reg, TYPE(&stdouble), &d);
+
+ load_store_register(PC_STW, op->reg, temp_op.reg, temp_op.object, low_offset);
+
+ emitpcode(PC_LIS, tmp_reg = used_virtual_registers[RegClass_GPR]++, 0, 0x4330);
+ load_store_register(PC_STW, tmp_reg, temp_op.reg, temp_op.object, high_offset);
+
+ load_store_register(PC_LFD, work_reg = used_virtual_registers[RegClass_FPR]++, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_FPR]++;
+ if (is_single != 0)
+ opcode = PC_FSUBS;
+ else
+ opcode = PC_FSUB;
+ emitpcode(opcode, result_reg, work_reg, const_reg);
+
+ op->optype = OpndType_FPR;
+ op->reg = result_reg;
+}
+
+void convert_floating_to_integer(Operand *op, short output_reg) {
+ Operand temp_op;
+ int tmp_reg;
+ int result_reg;
+
+ symbol_operand(&temp_op, maketemporary(TYPE(&stdouble)));
+ coerce_to_addressable(&temp_op);
+
+ tmp_reg = used_virtual_registers[RegClass_FPR]++;
+ emitpcode(PC_FCTIWZ, tmp_reg, op->reg);
+ load_store_register(PC_STFD, tmp_reg, temp_op.reg, temp_op.object, 0);
+
+ result_reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LWZ, result_reg, temp_op.reg, temp_op.object, low_offset);
+
+ op->optype = OpndType_GPR;
+ op->reg = result_reg;
+}
+
+void convert_floating_to_unsigned(Operand *op, short output_reg) {
+ static UInt32 used_regs[RegClassMax] = {0, 0, 0, 2, 0};
+
+ if (op->reg != 1)
+ emitpcode(PC_FMR, 1, op->reg);
+
+ branch_subroutine(rt_cvt_fp2unsigned, 0, used_regs);
+
+ op->optype = OpndType_GPR;
+ op->reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_MR, op->reg, 3);
+}
+
+void extract_bitfield(Operand *input_op, TypeBitfield *tbitfield, short output_reg, Operand *output_op) {
+ int r27;
+ int offset;
+ int tmp_reg;
+ int output;
+
+ offset = tbitfield->bitlength;
+ output = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
+ r27 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8));
+ if (is_unsigned(tbitfield->bitfieldtype)) {
+ emitpcode(PC_RLWINM, output, input_op->reg, (r27 + offset) & 31, 32 - offset, 31);
+ } else if (r27 == 0) {
+ emitpcode(PC_SRAWI, output, input_op->reg, 32 - offset);
+ } else {
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmp_reg, input_op->reg, r27 & 31, 0, offset);
+ emitpcode(PC_SRAWI, output, tmp_reg, 32 - offset);
+ }
+
+ output_op->optype = OpndType_GPR;
+ output_op->reg = output;
+}
+
+void insert_bitfield(short reg, Operand *op, TypeBitfield *tbitfield) {
+ int offset = tbitfield->bitlength;
+ int r7 = tbitfield->offset + (32 - (tbitfield->bitfieldtype->size * 8));
+ emitpcode(PC_RLWIMI, op->reg, reg, 32 - (r7 + offset), r7, r7 + offset - 1);
+}
+
+void load_address(short dest_reg, Operand *op) {
+ coerce_to_addressable(op);
+ if (op->optype == OpndType_IndirectGPR_ImmOffset) {
+ if (!op->immOffset && !op->object) {
+ if (op->reg != dest_reg)
+ emitpcode(PC_MR, dest_reg, op->reg);
+ } else {
+ add_immediate(dest_reg, op->reg, op->object, (SInt16) op->immOffset);
+ }
+ } else if (op->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(PC_ADD, dest_reg, op->reg, op->regOffset);
+ } else {
+ CError_FATAL(1849);
+ }
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c
new file mode 100644
index 0000000..368f8c5
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeAssembly.c
@@ -0,0 +1,1613 @@
+#include "compiler/PCodeAssembly.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeListing.h"
+#include "compiler/PPCError.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/TOC.h"
+#include "compiler/objects.h"
+
+static UInt32 codebase;
+
+static SInt32 pcode_update_mem_labeldiff_imm(PCode *instr, const PCodeArg *op, WeirdOperand *wop) {
+ SInt32 offset;
+ Object *object;
+ UInt8 arg;
+
+ if (op->kind == PCOp_MEMORY) {
+ object = op->data.mem.obj;
+ offset = op->data.mem.offset;
+ switch (object->datatype) {
+ case DLOCAL:
+ switch ((UInt8) op->arg) {
+ case RefType_1:
+ offset += local_offset_16(object);
+ break;
+ case RefType_D:
+ offset = local_offset_lo(object, offset);
+ break;
+ case RefType_C:
+ offset = local_offset_ha(object, offset);
+ break;
+ default:
+ CError_FATAL(83);
+ }
+ break;
+ case DDATA:
+ case DFUNC:
+ case DVFUNC:
+ case DNONLAZYPTR:
+ switch ((UInt8) op->arg) {
+ case RefType_6:
+ wop->type = MW_RELOC_5_LO16;
+ break;
+ case RefType_2:
+ wop->type = MW_RELOC_3;
+ break;
+ case RefType_3:
+ wop->type = MW_RELOC_4;
+ break;
+ case RefType_8:
+ wop->type = MW_RELOC_7_HA16;
+ break;
+ case RefType_7:
+ wop->type = MW_RELOC_6_HI16;
+ break;
+ default:
+ CError_FATAL(135);
+ }
+
+ wop->x2 = object;
+ CError_ASSERT(144, offset == 0);
+ break;
+ default:
+ CError_FATAL(164);
+ }
+ } else if (op->kind == PCOp_LABELDIFF) {
+ arg = op->arg;
+
+ offset = op->data.labeldiff.labelA->block->codeOffset - op->data.labeldiff.labelB->block->codeOffset;
+ offset += op->data.labeldiff.offset;
+ if (arg == 1)
+ offset = -offset;
+
+ if (offset > 0x7FFF)
+ PPCError_Error(PPCErrorStr109);
+ else if (offset < -0x8000)
+ PPCError_Error(PPCErrorStr109);
+ } else if (op->kind == PCOp_IMMEDIATE) {
+ offset = op->data.imm.value;
+ } else {
+ CError_FATAL(193);
+ }
+
+ return offset;
+}
+
+UInt32 assemblepcode(PCode *instr, UInt32 offset, WeirdOperand *wop) {
+ UInt32 bits;
+
+ bits = opcodeinfo[instr->op].insn;
+ wop->type = -1;
+ wop->x6 = 0;
+
+ switch (instr->op) {
+ case PC_BL: {
+ int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
+ if (instr->args[0].kind == PCOp_MEMORY) {
+ bits |= instr->args[0].data.mem.offset & 0x3FFFFFC;
+ wop->type = MW_RELOC_2_BR24;
+ wop->x2 = instr->args[0].data.mem.obj;
+ if (flag == 0)
+ wop->type = MW_RELOC_2_BR24;
+ else
+ CError_FATAL(246);
+ } else if (instr->args[0].kind == PCOp_IMMEDIATE) {
+ bits |= instr->args[0].data.imm.value & 0x3FFFFFC;
+ if (flag)
+ bits |= 2;
+ } else {
+ bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC;
+ if (flag)
+ CError_FATAL(261);
+ }
+ break;
+ }
+
+ case PC_B: {
+ int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
+ if (instr->args[0].kind == PCOp_MEMORY) {
+ bits |= instr->args[0].data.mem.offset & 0x3FFFFFC;
+ wop->x2 = instr->args[0].data.mem.obj;
+ if (flag == 0)
+ wop->type = MW_RELOC_2_BR24;
+ else
+ CError_FATAL(288);
+ } else if (instr->args[0].kind == PCOp_IMMEDIATE) {
+ bits |= instr->args[0].data.imm.value & 0x3FFFFFC;
+ if (flag)
+ bits |= 2;
+ } else {
+ bits |= (instr->args[0].data.label.label->block->codeOffset - offset) & 0x3FFFFFC;
+ if (flag)
+ CError_FATAL(302);
+ }
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ break;
+ }
+
+ case PC_BDNZ:
+ case PC_BDZ: {
+ int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
+ if (instr->args[0].kind == PCOp_MEMORY) {
+ bits |= instr->args[0].data.mem.offset & 0xFFFC;
+ wop->x2 = instr->args[0].data.mem.obj;
+ if (flag == 0)
+ wop->type = MW_RELOC_8;
+ else
+ CError_FATAL(333);
+ } else {
+ SInt32 value;
+ if (instr->args[0].kind == PCOp_IMMEDIATE)
+ value = instr->args[0].data.imm.value;
+ else
+ value = instr->args[0].data.label.label->block->codeOffset - offset;
+
+ bits |= value & 0xFFFF;
+ if (value < 0) {
+ if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
+ bits |= 0x200000u;
+ } else {
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ bits |= 0x200000u;
+ }
+ }
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ break;
+ }
+
+ case PC_BC: {
+ int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
+ bits |= (instr->args[0].data.imm.value & 31) << 21;
+ bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16;
+
+ if (instr->args[3].kind == PCOp_MEMORY) {
+ bits |= instr->args[3].data.mem.offset & 0xFFFC;
+ wop->x2 = instr->args[3].data.mem.obj;
+ if (flag == 0)
+ wop->type = MW_RELOC_8;
+ else
+ CError_FATAL(387);
+ } else {
+ SInt32 value;
+ if (instr->args[3].kind == PCOp_IMMEDIATE)
+ value = instr->args[3].data.imm.value;
+ else
+ value = instr->args[3].data.label.label->block->codeOffset - offset;
+
+ bits |= value & 0xFFFF;
+ if (value < 0) {
+ if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
+ bits |= 0x200000u;
+ } else {
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ bits |= 0x200000u;
+ }
+ }
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ break;
+ }
+
+ case PC_BT:
+ case PC_BF:
+ case PC_BDNZT:
+ case PC_BDNZF:
+ case PC_BDZT:
+ case PC_BDZF: {
+ int flag = PCODE_FLAG_SET_T(instr) & fAbsolute;
+ bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16;
+
+ if (instr->args[2].kind == PCOp_MEMORY) {
+ bits |= instr->args[2].data.mem.offset & 0xFFFC;
+ wop->x2 = instr->args[2].data.mem.obj;
+ if (flag == 0)
+ wop->type = MW_RELOC_8;
+ else
+ CError_FATAL(446);
+ } else {
+ SInt32 value;
+ if (instr->args[2].kind == PCOp_IMMEDIATE) {
+ value = instr->args[2].data.imm.value;
+ if (flag)
+ bits |= 2;
+ } else {
+ value = instr->args[2].data.label.label->block->codeOffset - offset;
+ CError_ASSERT(458, !flag);
+ }
+
+ bits |= value & 0xFFFF;
+
+ if (value < 0) {
+ if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
+ bits |= 0x200000u;
+ } else {
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ bits |= 0x200000u;
+ }
+ }
+
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ break;
+ }
+
+ case PC_BTLR:
+ case PC_BTCTR:
+ case PC_BFLR:
+ case PC_BFCTR:
+ bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 16;
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ bits |= 0x200000u;
+ break;
+
+ case PC_BCLR:
+ case PC_BCCTR:
+ bits |= instr->args[0].data.imm.value << 21;
+ bits |= ((instr->args[1].data.reg.reg * 4 + instr->args[2].data.imm.value) & 31) << 16;
+ case PC_BLR:
+ case PC_BCTR:
+ case PC_BCTRL:
+ case PC_BLRL:
+ if (PCODE_FLAG_SET_T(instr) & fLink)
+ bits |= 1;
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ bits |= 0x200000u;
+ break;
+
+ case PC_CRAND:
+ case PC_CRANDC:
+ case PC_CREQV:
+ case PC_CRNAND:
+ case PC_CRNOR:
+ case PC_CROR:
+ case PC_CRORC:
+ case PC_CRXOR:
+ bits |= ((instr->args[0].data.reg.reg * 4 + instr->args[1].data.imm.value) & 31) << 21;
+ bits |= ((instr->args[2].data.reg.reg * 4 + instr->args[3].data.imm.value) & 31) << 16;
+ bits |= ((instr->args[4].data.reg.reg * 4 + instr->args[5].data.imm.value) & 31) << 11;
+ break;
+
+ case PC_MCRF:
+ bits |= instr->args[0].data.reg.reg << 23;
+ bits |= instr->args[1].data.reg.reg << 18;
+ break;
+
+ case PC_LBZ:
+ case PC_LBZU:
+ case PC_LHZ:
+ case PC_LHZU:
+ case PC_LHA:
+ case PC_LHAU:
+ case PC_LWZ:
+ case PC_LWZU:
+ case PC_LMW:
+ case PC_STB:
+ case PC_STBU:
+ case PC_STH:
+ case PC_STHU:
+ case PC_STW:
+ case PC_STWU:
+ case PC_STMW:
+ case PC_LFS:
+ case PC_LFSU:
+ case PC_LFD:
+ case PC_LFDU:
+ case PC_STFS:
+ case PC_STFSU:
+ case PC_STFD:
+ case PC_STFDU:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
+ break;
+
+ case PC_LBZX:
+ case PC_LBZUX:
+ case PC_LHZX:
+ case PC_LHZUX:
+ case PC_LHAX:
+ case PC_LHAUX:
+ case PC_LHBRX:
+ case PC_LWZX:
+ case PC_LWZUX:
+ case PC_LWBRX:
+ case PC_STBX:
+ case PC_STBUX:
+ case PC_STHX:
+ case PC_STHUX:
+ case PC_STHBRX:
+ case PC_STWX:
+ case PC_STWUX:
+ case PC_STWBRX:
+ case PC_LFSX:
+ case PC_LFSUX:
+ case PC_LFDX:
+ case PC_LFDUX:
+ case PC_STFSX:
+ case PC_STFSUX:
+ case PC_STFDX:
+ case PC_STFDUX:
+ case PC_LWARX:
+ case PC_LSWX:
+ case PC_STFIWX:
+ case PC_STSWX:
+ case PC_STWCX:
+ case PC_ECIWX:
+ case PC_ECOWX:
+ case PC_DCREAD:
+ case PC_TLBSX:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_DCBF:
+ case PC_DCBST:
+ case PC_DCBT:
+ case PC_DCBTST:
+ case PC_DCBZ:
+ case PC_DCBI:
+ case PC_ICBI:
+ case PC_DCCCI:
+ case PC_ICBT:
+ case PC_ICCCI:
+ case PC_ICREAD:
+ case PC_DCBA:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 11;
+ break;
+
+ case PC_ADD:
+ case PC_ADDC:
+ case PC_ADDE:
+ case PC_DIVW:
+ case PC_DIVWU:
+ case PC_MULHW:
+ case PC_MULHWU:
+ case PC_MULLW:
+ case PC_SUBF:
+ case PC_SUBFC:
+ case PC_SUBFE:
+ bits |= instr->args[2].data.reg.reg << 11;
+ case PC_ADDME:
+ case PC_ADDZE:
+ case PC_NEG:
+ case PC_SUBFME:
+ case PC_SUBFZE:
+ case PC_MFROM:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ if (PCODE_FLAG_SET_F(instr) & fOverflow)
+ bits |= 0x400;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_ADDI:
+ case PC_ADDIC:
+ case PC_ADDICR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
+ break;
+
+ case PC_ADDIS:
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
+ break;
+
+ case PC_MULLI:
+ case PC_SUBFIC:
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[2].data.imm.value & 0xFFFF;
+ break;
+
+ case PC_LI:
+ case PC_LIS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[1], wop) & 0xFFFF;
+ break;
+
+ case PC_ANDI:
+ case PC_ANDIS:
+ case PC_ORI:
+ case PC_ORIS:
+ case PC_XORI:
+ case PC_XORIS:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= pcode_update_mem_labeldiff_imm(instr, &instr->args[2], wop) & 0xFFFF;
+ break;
+
+ case PC_AND:
+ case PC_OR:
+ case PC_XOR:
+ case PC_NAND:
+ case PC_NOR:
+ case PC_EQV:
+ case PC_ANDC:
+ case PC_ORC:
+ case PC_SLW:
+ case PC_SRW:
+ case PC_SRAW:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_EXTSH:
+ case PC_EXTSB:
+ case PC_CNTLZW:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_MR:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_NOT:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_SRAWI:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= (instr->args[2].data.imm.value & 31) << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_RLWINM:
+ case PC_RLWIMI:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= (instr->args[2].data.imm.value & 31) << 11;
+ bits |= (instr->args[3].data.imm.value & 31) << 6;
+ bits |= (instr->args[4].data.imm.value & 31) << 1;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_RLWNM:
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[2].data.reg.reg << 11;
+ bits |= (instr->args[3].data.imm.value & 31) << 6;
+ bits |= (instr->args[4].data.imm.value & 31) << 1;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_CMP:
+ case PC_CMPL:
+ bits |= instr->args[0].data.reg.reg << 23;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ break;
+
+ case PC_CMPI:
+ case PC_CMPLI:
+ bits |= instr->args[0].data.reg.reg << 23;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.imm.value & 0xFFFF;
+ break;
+
+ case PC_MTXER:
+ case PC_MTCTR:
+ case PC_MTLR:
+ case PC_MTMSR:
+ case PC_MFMSR:
+ case PC_MFXER:
+ case PC_MFCTR:
+ case PC_MFLR:
+ case PC_MFCR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ break;
+
+ case PC_MFFS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_MTCRF:
+ bits |= instr->args[0].data.imm.value << 12;
+ bits |= instr->args[1].data.reg.reg << 21;
+ break;
+
+ case PC_MTFSF:
+ bits |= (instr->args[0].data.imm.value & 0xFF) << 17;
+ bits |= instr->args[1].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_FMR:
+ case PC_FABS:
+ case PC_FNEG:
+ case PC_FNABS:
+ case PC_FRES:
+ case PC_FRSQRTE:
+ case PC_FRSP:
+ case PC_FCTIW:
+ case PC_FCTIWZ:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_FADD:
+ case PC_FADDS:
+ case PC_FSUB:
+ case PC_FSUBS:
+ case PC_FDIV:
+ case PC_FDIVS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_FMADD:
+ case PC_FMADDS:
+ case PC_FMSUB:
+ case PC_FMSUBS:
+ case PC_FNMADD:
+ case PC_FNMADDS:
+ case PC_FNMSUB:
+ case PC_FNMSUBS:
+ case PC_FSEL:
+ bits |= instr->args[3].data.reg.reg << 11;
+ case PC_FMUL:
+ case PC_FMULS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 6;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_FCMPU:
+ case PC_FCMPO:
+ bits |= instr->args[0].data.reg.reg << 23;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ break;
+
+ case PC_MTSPR:
+ if (instr->args[0].kind == PCOp_REGISTER) {
+ CError_ASSERT(1027, instr->args[0].arg == RegClass_SPR);
+ CError_ASSERT(1028, instr->args[0].data.reg.reg < 4);
+ bits |= ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x1F) << 16) +
+ ((spr_to_sysreg[instr->args[0].data.reg.reg] & 0x3E0) << 6);
+ } else if (instr->args[0].kind == PCOp_SYSREG && instr->args[0].arg == 0) {
+ bits |= ((instr->args[0].data.reg.reg & 0x1F) << 16) +
+ ((instr->args[0].data.reg.reg & 0x3E0) << 6);
+ } else {
+ CError_FATAL(1033);
+ }
+
+ bits |= instr->args[1].data.reg.reg << 21;
+ break;
+
+ case PC_MTDCR:
+ if (instr->args[0].kind == PCOp_IMMEDIATE) {
+ bits |= ((instr->args[0].data.imm.value & 0x1F) << 16) +
+ ((instr->args[0].data.imm.value & 0x3E0) << 6);
+ } else {
+ CError_FATAL(1042);
+ }
+
+ bits |= instr->args[1].data.reg.reg << 21;
+ break;
+
+ case PC_MFSPR:
+ bits |= instr->args[0].data.reg.reg << 21;
+
+ if (instr->args[1].kind == PCOp_REGISTER && instr->args[1].arg == RegClass_SPR) {
+ CError_ASSERT(1055, instr->args[1].data.reg.reg < 4);
+ bits |= ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x1F) << 16) +
+ ((spr_to_sysreg[instr->args[1].data.reg.reg] & 0x3E0) << 6);
+ } else if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) {
+ bits |= ((instr->args[1].data.reg.reg & 0x1F) << 16) +
+ ((instr->args[1].data.reg.reg & 0x3E0) << 6);
+ } else {
+ CError_FATAL(1060);
+ }
+ break;
+
+ case PC_MFDCR:
+ bits |= instr->args[0].data.reg.reg << 21;
+
+ if (instr->args[1].kind == PCOp_IMMEDIATE) {
+ bits |= ((instr->args[1].data.imm.value & 0x1F) << 16) +
+ ((instr->args[1].data.imm.value & 0x3E0) << 6);
+ } else {
+ CError_FATAL(1069);
+ }
+ break;
+
+ case PC_LSWI:
+ case PC_STSWI:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= (instr->args[2].data.imm.value & 31) << 11;
+ break;
+
+ case PC_MCRFS:
+ bits |= (instr->args[1].data.imm.value & 7) << 18;
+ case PC_MCRXR:
+ bits |= instr->args[0].data.reg.reg << 23;
+ break;
+
+ case PC_MFTB:
+ bits |= instr->args[0].data.reg.reg << 21;
+ if (instr->args[1].kind == PCOp_SYSREG && instr->args[1].arg == 0) {
+ if (instr->args[1].data.reg.reg == 284)
+ bits |= 0xC4000u;
+ else if (instr->args[1].data.reg.reg == 285)
+ bits |= 0xD4000u;
+ else
+ CError_FATAL(1100);
+ } else {
+ CError_FATAL(1103);
+ }
+ break;
+
+ case PC_MTSR:
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= (instr->args[0].data.imm.value & 15) << 16;
+ break;
+
+ case PC_MFSR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= (instr->args[1].data.imm.value & 15) << 16;
+ break;
+
+ case PC_MFSRIN:
+ case PC_MTSRIN:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ break;
+
+ case PC_MTFSB0:
+ case PC_MTFSB1:
+ bits |= (instr->args[0].data.imm.value & 31) << 21;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_MTFSFI:
+ bits |= instr->args[0].data.reg.reg << 23;
+ bits |= (instr->args[1].data.imm.value & 15) << 12;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_FSQRT:
+ case PC_FSQRTS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_TLBIE:
+ case PC_TLBLD:
+ case PC_TLBLI:
+ bits |= instr->args[0].data.reg.reg << 11;
+ break;
+
+ case PC_TW:
+ bits |= (instr->args[0].data.imm.value & 31) << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ break;
+
+ case PC_TWI:
+ bits |= (instr->args[0].data.imm.value & 31) << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.imm.value & 0xFFFF;
+ break;
+
+ case PC_OPWORD:
+ CError_ASSERT(1176, instr->args[0].kind != PCOp_MEMORY);
+ bits = pcode_update_mem_labeldiff_imm(instr, &instr->args[0], wop);
+ break;
+
+ case PC_MASKG:
+ case PC_MASKIR:
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_LSCBX:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_DIV:
+ case PC_DIVS:
+ case PC_DOZ:
+ case PC_MUL:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fOverflow)
+ bits |= 0x400;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_NABS:
+ case PC_ABS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ if (PCODE_FLAG_SET_F(instr) & fOverflow)
+ bits |= 0x400;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_CLCS:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_DOZI:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.imm.value & 0xFFFF;
+ break;
+
+ case PC_RLMI:
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ bits |= (instr->args[3].data.imm.value & 31) << 6;
+ bits |= (instr->args[4].data.imm.value & 31) << 1;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_SLE:
+ case PC_SLEQ:
+ case PC_SLLQ:
+ case PC_SLQ:
+ case PC_SRAQ:
+ case PC_SRE:
+ case PC_SREA:
+ case PC_SREQ:
+ case PC_SRLQ:
+ case PC_SRQ:
+ case PC_RRIB:
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_SLIQ:
+ case PC_SLLIQ:
+ case PC_SRAIQ:
+ case PC_SRIQ:
+ case PC_SRLIQ:
+ bits |= instr->args[1].data.reg.reg << 21;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= (instr->args[2].data.imm.value & 31) << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 1;
+ break;
+
+ case PC_TLBRE:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= (instr->args[2].data.imm.value & 1) << 11;
+ break;
+
+ case PC_TLBWE:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= (instr->args[2].data.imm.value & 1) << 11;
+ break;
+
+ case PC_WRTEE:
+ bits |= instr->args[0].data.reg.reg << 21;
+ break;
+
+ case PC_WRTEEI:
+ bits |= instr->args[0].data.imm.value << 15;
+ break;
+
+ case PC_DSTT:
+ case PC_DSTSTT:
+ bits |= 0x2000000u;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 11;
+ bits |= (instr->args[2].data.imm.value & 3) << 21;
+ break;
+
+ case PC_DST:
+ case PC_DSTST:
+ bits |= (instr->args[3].data.imm.value & 1) << 25;
+ bits |= instr->args[0].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 11;
+ bits |= (instr->args[2].data.imm.value & 3) << 21;
+ break;
+
+ case PC_DSSALL:
+ bits |= 0x2000000u;
+ break;
+
+ case PC_DSS:
+ bits |= (instr->args[1].data.imm.value & 1) << 25;
+ bits |= (instr->args[0].data.imm.value & 3) << 21;
+ break;
+
+ case PC_LVEBX:
+ case PC_LVEHX:
+ case PC_LVEWX:
+ case PC_LVSL:
+ case PC_LVSR:
+ case PC_LVX:
+ case PC_LVXL:
+ case PC_STVEBX:
+ case PC_STVEHX:
+ case PC_STVEWX:
+ case PC_STVX:
+ case PC_STVXL:
+ case PC_VADDCUW:
+ case PC_VADDFP:
+ case PC_VADDSBS:
+ case PC_VADDSHS:
+ case PC_VADDSWS:
+ case PC_VADDUBM:
+ case PC_VADDUBS:
+ case PC_VADDUHM:
+ case PC_VADDUHS:
+ case PC_VADDUWM:
+ case PC_VADDUWS:
+ case PC_VAND:
+ case PC_VANDC:
+ case PC_VAVGSB:
+ case PC_VAVGSH:
+ case PC_VAVGSW:
+ case PC_VAVGUB:
+ case PC_VAVGUH:
+ case PC_VAVGUW:
+ case PC_VMAXFP:
+ case PC_VMAXSB:
+ case PC_VMAXSH:
+ case PC_VMAXSW:
+ case PC_VMAXUB:
+ case PC_VMAXUH:
+ case PC_VMAXUW:
+ case PC_VMINFP:
+ case PC_VMINSB:
+ case PC_VMINSH:
+ case PC_VMINSW:
+ case PC_VMINUB:
+ case PC_VMINUH:
+ case PC_VMINUW:
+ case PC_VMRGHB:
+ case PC_VMRGHH:
+ case PC_VMRGHW:
+ case PC_VMRGLB:
+ case PC_VMRGLH:
+ case PC_VMRGLW:
+ case PC_VMULESB:
+ case PC_VMULESH:
+ case PC_VMULEUB:
+ case PC_VMULEUH:
+ case PC_VMULOSB:
+ case PC_VMULOSH:
+ case PC_VMULOUB:
+ case PC_VMULOUH:
+ case PC_VNOR:
+ case PC_VOR:
+ case PC_VPKPX:
+ case PC_VPKSHSS:
+ case PC_VPKSHUS:
+ case PC_VPKSWSS:
+ case PC_VPKSWUS:
+ case PC_VPKUHUM:
+ case PC_VPKUHUS:
+ case PC_VPKUWUM:
+ case PC_VPKUWUS:
+ case PC_VRLB:
+ case PC_VRLH:
+ case PC_VRLW:
+ case PC_VSL:
+ case PC_VSLB:
+ case PC_VSLH:
+ case PC_VSLO:
+ case PC_VSLW:
+ case PC_VSR:
+ case PC_VSRAB:
+ case PC_VSRAH:
+ case PC_VSRAW:
+ case PC_VSRB:
+ case PC_VSRH:
+ case PC_VSRO:
+ case PC_VSRW:
+ case PC_VSUBCUW:
+ case PC_VSUBFP:
+ case PC_VSUBSBS:
+ case PC_VSUBSHS:
+ case PC_VSUBSWS:
+ case PC_VSUBUBM:
+ case PC_VSUBUBS:
+ case PC_VSUBUHM:
+ case PC_VSUBUHS:
+ case PC_VSUBUWM:
+ case PC_VSUBUWS:
+ case PC_VSUMSWS:
+ case PC_VSUM2SWS:
+ case PC_VSUM4SBS:
+ case PC_VSUM4SHS:
+ case PC_VSUM4UBS:
+ case PC_VXOR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ break;
+
+ case PC_VCFSX:
+ case PC_VCFUX:
+ case PC_VCTSXS:
+ case PC_VCTUXS:
+ case PC_VSPLTB:
+ case PC_VSPLTH:
+ case PC_VSPLTW:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ bits |= (instr->args[2].data.imm.value & 31) << 16;
+ break;
+
+ case PC_VEXPTEFP:
+ case PC_VLOGEFP:
+ case PC_VREFP:
+ case PC_VRFIM:
+ case PC_VRFIN:
+ case PC_VRFIP:
+ case PC_VRFIZ:
+ case PC_VRSQRTEFP:
+ case PC_VUPKHPX:
+ case PC_VUPKHSB:
+ case PC_VUPKHSH:
+ case PC_VUPKLPX:
+ case PC_VUPKLSB:
+ case PC_VUPKLSH:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 11;
+ break;
+
+ case PC_VCMPBFP:
+ case PC_VCMPEQFP:
+ case PC_VCMPEQUB:
+ case PC_VCMPEQUH:
+ case PC_VCMPEQUW:
+ case PC_VCMPGEFP:
+ case PC_VCMPGTFP:
+ case PC_VCMPGTSB:
+ case PC_VCMPGTSH:
+ case PC_VCMPGTSW:
+ case PC_VCMPGTUB:
+ case PC_VCMPGTUH:
+ case PC_VCMPGTUW:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ bits |= 0x400;
+ break;
+
+ case PC_VSPLTISB:
+ case PC_VSPLTISH:
+ case PC_VSPLTISW:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= (instr->args[1].data.imm.value & 31) << 16;
+ break;
+
+ case PC_VMHADDSHS:
+ case PC_VMHRADDSHS:
+ case PC_VMLADDUHM:
+ case PC_VMSUMMBM:
+ case PC_VMSUMSHM:
+ case PC_VMSUMSHS:
+ case PC_VMSUMUBM:
+ case PC_VMSUMUHM:
+ case PC_VMSUMUHS:
+ case PC_VPERM:
+ case PC_VSEL:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ bits |= instr->args[3].data.reg.reg << 6;
+ break;
+
+ case PC_VMADDFP:
+ case PC_VNMSUBFP:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 6;
+ bits |= instr->args[3].data.reg.reg << 11;
+ break;
+
+ case PC_VSLDOI:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[2].data.reg.reg << 11;
+ bits |= (instr->args[3].data.imm.value & 15) << 6;
+ break;
+
+ case PC_VMR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 11;
+ break;
+
+ case PC_VMRP:
+ bits |= instr->args[0].data.reg.reg << 21;
+ bits |= instr->args[1].data.reg.reg << 16;
+ bits |= instr->args[1].data.reg.reg << 11;
+ break;
+
+ case PC_MFVSCR:
+ bits |= instr->args[0].data.reg.reg << 21;
+ break;
+
+ case PC_MTVSCR:
+ bits |= instr->args[0].data.reg.reg << 11;
+ break;
+
+ case PC_EIEIO:
+ case PC_ISYNC:
+ case PC_SYNC:
+ case PC_RFI:
+ case PC_NOP:
+ case PC_SC:
+ case PC_TLBIA:
+ case PC_TLBSYNC:
+ case PC_TRAP:
+ case PC_DSA:
+ case PC_ESA:
+ case PC_RFCI:
+ break;
+
+ default:
+ CError_FATAL(2203);
+ }
+
+ return CTool_EndianConvertWord32(bits);
+}
+
+static PCode *targetinstruction(PCodeLabel *label) {
+ PCodeBlock *block = label->block;
+ while (block->pcodeCount == 0)
+ block = block->nextBlock;
+ return block->firstPCode;
+}
+
+static void invertybit(PCode *instr, SInt32 value) {
+ if (instr->op == PC_BC) {
+ if (instr->args[0].data.imm.value & 1) {
+ if (value < 0)
+ instr->flags |= fBranchNotTaken;
+ else
+ instr->flags |= fBranchTaken;
+ }
+ } else if (instr->op == PC_BCCTR || instr->op == PC_BCLR) {
+ if (instr->args[0].data.imm.value & 1)
+ instr->flags |= fBranchTaken;
+ }
+
+ if (PCODE_FLAG_SET_T(instr) & fBranchTaken)
+ instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken;
+ else if (PCODE_FLAG_SET_T(instr) & fBranchNotTaken)
+ instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken;
+ else if (value < 0)
+ instr->flags = (instr->flags & ~fBranchTaken) | fBranchNotTaken;
+ else
+ instr->flags = (instr->flags & ~fBranchNotTaken) | fBranchTaken;
+}
+
+static void insertlongbranches(SInt32 mask) {
+ PCodeBlock *block;
+ PCodeLabel *label;
+ SInt32 i;
+
+ i = 0;
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ block->codeOffset = i;
+ if (block->pcodeCount) {
+ i += block->pcodeCount * 4;
+ if (block->pcodeCount && (block->lastPCode->flags & fIsBranch))
+ i += 4;
+ }
+ }
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (block->pcodeCount && (block->lastPCode->flags & fIsBranch)) {
+ switch (block->lastPCode->op) {
+ case PC_BT:
+ case PC_BF:
+ i = block->codeOffset + ((block->pcodeCount - 1) * 4);
+ if (block->lastPCode->args[2].kind == PCOp_LABEL) {
+ label = block->lastPCode->args[2].data.label.label;
+ i = label->block->codeOffset - i;
+ if (i != ((SInt16) (i & mask))) {
+ block->lastPCode->op = (block->lastPCode->op == PC_BT) ? PC_BF : PC_BT;
+ block->lastPCode->args[2].data.label.label = block->nextBlock->labels;
+ invertybit(block->lastPCode, i);
+ appendpcode(block, makepcode(PC_B, label));
+ }
+ }
+ break;
+
+ case PC_BC:
+ i = block->codeOffset + ((block->pcodeCount - 1) * 4);
+ if (block->lastPCode->args[3].kind == PCOp_LABEL) {
+ label = block->lastPCode->args[3].data.label.label;
+ i = label->block->codeOffset - i;
+ invertybit(block->lastPCode, i);
+ if (i != ((SInt16) (i & mask))) {
+ switch (block->lastPCode->args[0].data.imm.value & 30) {
+ case 0:
+ case 2:
+ case 8:
+ case 10:
+ block->lastPCode->args[0].data.imm.value ^= 11;
+ block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
+ break;
+ case 16:
+ case 18:
+ block->lastPCode->args[0].data.imm.value ^= 3;
+ block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
+ break;
+ case 4:
+ case 12:
+ block->lastPCode->args[0].data.imm.value ^= 9;
+ block->lastPCode->args[3].data.label.label = block->nextBlock->labels;
+ break;
+ case 20:
+ deletepcode(block->lastPCode);
+ break;
+ default:
+ CError_FATAL(2368);
+ }
+
+ appendpcode(block, makepcode(PC_B, label));
+ }
+ }
+ break;
+
+ case PC_BDNZ:
+ case PC_BDZ:
+ i = block->codeOffset + ((block->pcodeCount - 1) * 4);
+ if (block->lastPCode->args[0].kind == PCOp_LABEL) {
+ label = block->lastPCode->args[0].data.label.label;
+ i = label->block->codeOffset - i;
+ if (i != ((SInt16) (i & mask))) {
+ switch (block->lastPCode->op) {
+ case PC_BDZ:
+ block->lastPCode->op = PC_BDNZ;
+ break;
+ case PC_BDNZ:
+ block->lastPCode->op = PC_BDZ;
+ break;
+ default:
+ CError_FATAL(2389);
+ }
+
+ block->lastPCode->args[0].data.label.label = block->nextBlock->labels;
+ invertybit(block->lastPCode, i);
+ appendpcode(block, makepcode(PC_B, label));
+ }
+ }
+ break;
+
+ case PC_BDNZT:
+ case PC_BDNZF:
+ case PC_BDZT:
+ case PC_BDZF:
+ i = block->codeOffset + ((block->pcodeCount - 1) * 4);
+ if (block->lastPCode->args[2].kind == PCOp_LABEL) {
+ label = block->lastPCode->args[2].data.label.label;
+ i = label->block->codeOffset - i;
+ if (i != ((SInt16) (i & mask))) {
+ switch (block->lastPCode->op) {
+ case PC_BDNZT:
+ block->lastPCode->op = PC_BDZF;
+ break;
+ case PC_BDNZF:
+ block->lastPCode->op = PC_BDZT;
+ break;
+ case PC_BDZT:
+ block->lastPCode->op = PC_BDNZF;
+ break;
+ case PC_BDZF:
+ block->lastPCode->op = PC_BDNZT;
+ break;
+ default:
+ CError_FATAL(2420);
+ }
+
+ block->lastPCode->args[2].data.label.label = block->nextBlock->labels;
+ invertybit(block->lastPCode, i);
+ appendpcode(block, makepcode(PC_B, label));
+ }
+ }
+ break;
+
+ }
+ }
+ }
+}
+
+SInt32 optimizefinalbranches(SInt32 codesize) {
+ PCodeBlock *block;
+ PCode *instr;
+ SInt32 offset;
+ int changed;
+ int deleted;
+ PCodeLabel *label;
+ PCode *target;
+
+ do {
+ changed = deleted = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (block->pcodeCount == 0)
+ continue;
+
+ instr = block->lastPCode;
+ if (!(instr->flags & fIsBranch))
+ continue;
+
+ offset = block->codeOffset + (block->pcodeCount - 1) * 4;
+
+ if (instr->op == PC_B && instr->args[0].kind == PCOp_LABEL) {
+ label = instr->args[0].data.label.label;
+ target = targetinstruction(label);
+
+ if (label->block->codeOffset == (offset + 4)) {
+ deletepcode(instr);
+ changed = deleted = 1;
+ } else if (target->op == PC_B) {
+ if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[0].data.label.label) {
+ instr->args[0].data.label.label = target->args[0].data.label.label;
+ changed = 1;
+ }
+ } else if (target->op == PC_BLR) {
+ instr->op = PC_BLR;
+ changed = 1;
+ }
+ continue;
+ }
+
+ if ((instr->op == PC_BT || instr->op == PC_BF) && instr->args[2].kind == PCOp_LABEL) {
+ PCodeBlock *block2 = instr->block;
+ label = instr->args[2].data.label.label;
+ target = targetinstruction(label);
+
+ if (label->block->codeOffset == (offset + 4)) {
+ deletepcode(instr);
+ changed = deleted = 1;
+ } else if (target->op == PC_B) {
+ if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[2].data.label.label) {
+ instr->args[2].data.label.label = target->args[0].data.label.label;
+ changed = 1;
+ }
+ } else if (copts.opt_bcc_lr_ctr) {
+ if (target->op == PC_BLR) {
+ if (instr->op == PC_BT)
+ instr->op = PC_BTLR;
+ else
+ instr->op = PC_BFLR;
+ instr->argCount = 2;
+ changed = 1;
+ } else if (target->op == PC_BCTR) {
+ if (instr->op == PC_BT)
+ instr->op = PC_BTCTR;
+ else
+ instr->op = PC_BFCTR;
+ instr->argCount = 2;
+ changed = 1;
+ } else if (
+ block2->nextBlock &&
+ block2->nextBlock->firstPCode &&
+ block2->nextBlock->firstPCode->op == PC_BLR &&
+ label->block->codeOffset == (offset + 8)
+ ) {
+ if (
+ block2->nextBlock->predecessors &&
+ block2->nextBlock->predecessors->block == block2 &&
+ !block2->nextBlock->predecessors->nextLink
+ ) {
+ if (instr->op == PC_BT)
+ instr->op = PC_BFLR;
+ else
+ instr->op = PC_BTLR;
+ change_num_operands(instr, 2);
+ deletepcode(block2->nextBlock->firstPCode);
+ changed = deleted = 1;
+ }
+ } else if (
+ block2->nextBlock &&
+ block2->nextBlock->firstPCode &&
+ block2->nextBlock->firstPCode->op == PC_BCTR &&
+ label->block->codeOffset == (offset + 8)
+ ) {
+ if (
+ block2->nextBlock->predecessors &&
+ block2->nextBlock->predecessors->block == block2 &&
+ !block2->nextBlock->predecessors->nextLink
+ ) {
+ if (instr->op == PC_BT)
+ instr->op = PC_BFCTR;
+ else
+ instr->op = PC_BTCTR;
+ change_num_operands(instr, 2);
+ deletepcode(block2->nextBlock->firstPCode);
+ changed = deleted = 1;
+ }
+ }
+ }
+ continue;
+ }
+
+ if (
+ instr->op == PC_BC &&
+ instr->args[3].kind == PCOp_LABEL &&
+ !(PCODE_FLAG_SET_T(instr) & (fSideEffects | fLink))
+ )
+ {
+ PCodeBlock *block2 = instr->block;
+ label = instr->args[3].data.label.label;
+ target = targetinstruction(label);
+
+ if (label->block->codeOffset == (offset + 4)) {
+ deletepcode(instr);
+ changed = deleted = 1;
+ } else if (target->op == PC_B) {
+ if (target->args[0].kind == PCOp_LABEL && target->args[0].data.label.label != instr->args[3].data.label.label) {
+ instr->args[3].data.label.label = target->args[0].data.label.label;
+ changed = 1;
+ }
+ } else if (copts.opt_bcc_lr_ctr) {
+ if (target->op == PC_BLR) {
+ instr->op = PC_BCLR;
+ instr->argCount = 3;
+ changed = 1;
+ } else if (target->op == PC_BCTR) {
+ instr->op = PC_BCCTR;
+ instr->argCount = 3;
+ changed = 1;
+ } else if (
+ block2->nextBlock &&
+ block2->nextBlock->firstPCode &&
+ block2->nextBlock->firstPCode->op == PC_BLR &&
+ label->block->codeOffset == (offset + 8)
+ ) {
+ SInt32 val = instr->args[0].data.imm.value & 30;
+ if (
+ block2->nextBlock->predecessors &&
+ block2->nextBlock->predecessors->block == block2 &&
+ !block2->nextBlock->predecessors->nextLink
+ ) {
+ if ((val & 30) == 4)
+ instr->args[0].data.imm.value = val | 12;
+ else if ((val & 30) == 12)
+ instr->args[0].data.imm.value = val & 23;
+ instr->op = PC_BCLR;
+ instr->argCount = 3;
+ deletepcode(block2->nextBlock->firstPCode);
+ changed = deleted = 1;
+ }
+ } else if (
+ block2->nextBlock &&
+ block2->nextBlock->firstPCode &&
+ block2->nextBlock->firstPCode->op == PC_BCTR &&
+ label->block->codeOffset == (offset + 8)
+ ) {
+ SInt32 val = instr->args[0].data.imm.value & 30;
+ if (
+ block2->nextBlock->predecessors &&
+ block2->nextBlock->predecessors->block == block2 &&
+ !block2->nextBlock->predecessors->nextLink
+ ) {
+ if ((val & 30) == 4)
+ instr->args[0].data.imm.value = val | 12;
+ else if ((val & 30) == 12)
+ instr->args[0].data.imm.value = val & 23;
+ instr->op = PC_BCCTR;
+ instr->argCount = 3;
+ deletepcode(block2->nextBlock->firstPCode);
+ changed = deleted = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (deleted)
+ codesize = pccomputeoffsets();
+ } while (changed);
+
+ return codesize;
+}
+
+static SInt32 insert_align_nops(Object *func, SInt32 codesize) {
+ PCodeBlock *block;
+ int changed;
+ PCodeBlock *prev;
+
+ do {
+ changed = 0;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (
+ (block->flags & fPCBlockFlag6000) == fPCBlockFlag2000 &&
+ (block->codeOffset & 7) &&
+ block->pcodeCount < 8 &&
+ (prev = block->prevBlock) &&
+ !(prev->flags & fPCBlockFlag2000)
+ )
+ {
+ if (prev->lastPCode && prev->lastPCode->op == PC_NOP && !(prev->lastPCode->flags & fSideEffects)) {
+ deletepcode(prev->lastPCode);
+ } else {
+ PCode *nop = makepcode(PC_NOP);
+ nop->flags &= ~fSideEffects;
+ appendpcode(prev, nop);
+ }
+
+ codesize = pccomputeoffsets();
+ changed = 1;
+ }
+ }
+
+ if (changed) {
+ pclistblocks(CMangler_GetLinkName(func)->name, "AFTER INSERT ALIGN NOPs");
+ if (codesize > 32766) {
+ insertlongbranches(32766);
+ codesize = pccomputeoffsets();
+ }
+ }
+
+ } while (changed);
+
+ return codesize;
+}
+
+SInt32 assemblefunction(Object *func, EntryPoint *entrypoints) {
+ void *tbdata;
+ GList *gl;
+ PCodeBlock *block;
+ PCode *instr;
+ SInt32 offset2;
+ SInt32 codesize;
+ SInt32 tbsize;
+ SInt32 offset;
+ SectionHandle section;
+ EntryPoint *ep;
+ WeirdOperand wop;
+
+ codesize = pccomputeoffsets();
+ if (codesize <= 0)
+ PPCError_Error(PPCErrorStr190, func->name->name);
+
+ if (copts.peephole || copts.optimizationlevel >= 3)
+ codesize = optimizefinalbranches(codesize);
+
+ if (codesize > 32766) {
+ insertlongbranches(32766);
+ codesize = pccomputeoffsets();
+ }
+
+ if (copts.function_align > 4)
+ codesize = insert_align_nops(func, codesize);
+
+ tbsize = 0;
+ if (copts.traceback)
+ tbdata = generate_traceback(codesize, CMangler_GetLinkName(func)->name, &tbsize, func);
+
+ if (func->section == SECT_DEFAULT)
+ func->section = SECT_TEXT;
+
+ offset = tbsize;
+ section = ObjGen_DeclareCode(func, codesize + tbsize);
+ gl = ObjGen_GetSectionGList(section);
+
+ codebase = gl->size;
+ AppendGListNoData(gl, codesize + tbsize);
+
+ if (copts.filesyminfo) {
+ ObjGen_SymFunc(func);
+ ObjGen_Line(functionbodyoffset, 0);
+ ObjGen_DeclareSymInfo();
+ }
+
+ if (uses_globals && pic_base_reg)
+ ObjGen_DeclarePICBase(func, pic_base_pcodelabel->block->codeOffset);
+
+ if (entrypoints) {
+ for (ep = entrypoints; ep; ep = ep->next) {
+ ObjGen_DeclareEntry(ep->object, ep->block->codeOffset);
+ }
+ }
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (offset2 = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset2 += 4) {
+ if (copts.filesyminfo && instr->sourceoffset != -1)
+ ObjGen_Line(instr->sourceoffset, offset2);
+
+ *((UInt32 *) (*gl->data + codebase + offset2)) = assemblepcode(instr, offset2, &wop);
+
+ if (wop.type != -1)
+ ObjGen_RelocateObj(section, offset2, wop.x2, wop.type);
+ }
+ }
+
+ if (copts.filesyminfo)
+ ObjGenMach_SymFuncEnd(func, codesize);
+
+ if (copts.traceback)
+ memcpy(*gl->data + codebase + codesize, tbdata, offset);
+
+ if (copts.traceback)
+ return codesize + tbsize;
+ else
+ return codesize;
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c
new file mode 100644
index 0000000..7a9fa13
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeListing.c
@@ -0,0 +1,536 @@
+#include "compiler/PCodeListing.h"
+#include "compiler/CError.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/Alias.h"
+#include "compiler/BitVectors.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/InterferenceGraph.h"
+#include "compiler/LiveInfo.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeAssembly.h"
+#include "compiler/Registers.h"
+#include "compiler/Scheduler.h"
+#include "compiler/objects.h"
+
+static FILE *pcfile;
+static int ptime;
+static int sourcetext;
+static int sourcetext_is_main;
+static int sourcelength;
+int pclist_bad_operand;
+
+static void formatdataflowset(char *name, UInt32 *vec, UInt32 size, char *format) {
+ UInt32 i;
+ UInt32 counter;
+ char *separator;
+
+ separator = "";
+ fprintf(pcfile, "%s = {", name);
+
+ for (i = 0, counter = 0; i < size; i++) {
+ if (bitvectorgetbit(i, vec)) {
+ if (i)
+ fprintf(pcfile, separator);
+ if (counter++ == 10) {
+ fprintf(pcfile, "\n\t\t");
+ counter = 0;
+ }
+ fprintf(pcfile, format, i);
+ separator = ",";
+ }
+ }
+
+ fprintf(pcfile, "}\n");
+}
+
+static void pclistblock(PCodeBlock *block, char *format, UInt32 vecSize) {
+ PCLink *link;
+ PCodeLabel *label;
+ int cpu;
+ int chr;
+ PCode *instr;
+ int offset;
+ int latency;
+ UInt32 opcode;
+ MachineInfo *mi;
+ char buf[500];
+ WeirdOperand dummyArg;
+
+ fprintf(pcfile, ":{%4.4x}::::::::::::::::::::::::::::::::::::::::LOOPWEIGHT=%" PRId32 "\n", block->flags, block->loopWeight);
+ fprintf(pcfile, "B%" PRId32 ": ", block->blockIndex);
+
+ fprintf(pcfile, "Successors = { ");
+ for (link = block->successors; link; link = link->nextLink) {
+ if (link->block)
+ fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex);
+ }
+ fprintf(pcfile, "} ");
+
+ fprintf(pcfile, "Predecessors = { ");
+ for (link = block->predecessors; link; link = link->nextLink) {
+ if (link->block)
+ fprintf(pcfile, "B%" PRId32 " ", link->block->blockIndex);
+ }
+
+ if (block->labels) {
+ fprintf(pcfile, "} Labels = { ");
+ for (label = block->labels; label; label = label->nextLabel)
+ fprintf(pcfile, "L%" PRId32 " ", label->index);
+ }
+
+ fprintf(pcfile, "}\n\n");
+
+ cpu = copts.scheduling;
+ if (cpu == 10) {
+ mi = &machine7450;
+ } else if (copts.altivec_model != 0 || cpu == 7) {
+ mi = &machine7400;
+ } else if (cpu == 2) {
+ mi = &machine603;
+ } else if (cpu == 5) {
+ mi = &machine603e;
+ } else if (cpu == 3) {
+ mi = &machine604;
+ } else if (cpu == 6) {
+ mi = &machine604;
+ } else if (cpu == 4) {
+ mi = &machine750;
+ } else if (cpu == 1) {
+ mi = &machine601;
+ } else if (cpu == 9) {
+ mi = &machine821;
+ } else {
+ mi = &machine603;
+ }
+
+ for (offset = block->codeOffset, instr = block->firstPCode; instr; instr = instr->nextPCode, offset += 4) {
+ latency = mi->latency(instr);
+ formatoperands(instr, buf, 1);
+ chr = (PCODE_FLAG_SET_F(instr) & fRecordBit) ? '.' : ' ';
+ if (coloring)
+ opcode = 0;
+ else
+ opcode = assemblepcode(instr, offset, &dummyArg);
+
+ fprintf(
+ pcfile,
+ " %.8" PRIX32 " %.8" PRIX32 " %4" PRId32 " %-7s%c %s\n",
+ offset, CTool_EndianConvertWord32(opcode), latency,
+ opcodeinfo[instr->op].name, chr, buf
+ );
+
+ if (instr->alias)
+ dumpalias(instr->alias, 0, 1, 0);
+ }
+
+ if (vecSize) {
+ fprintf(pcfile, "............................................................\n");
+ formatdataflowset("use", liveinfo[block->blockIndex].use, vecSize, format);
+ formatdataflowset("def", liveinfo[block->blockIndex].def, vecSize, format);
+ formatdataflowset("in ", liveinfo[block->blockIndex].in, vecSize, format);
+ formatdataflowset("out", liveinfo[block->blockIndex].out, vecSize, format);
+ }
+
+ fflush(pcfile);
+
+ if (pclist_bad_operand)
+ CError_FATAL(252);
+}
+
+static void pclistonoff(int flag) {
+ if (flag)
+ fprintf(pcfile, "On\n");
+ else
+ fprintf(pcfile, "Off\n");
+}
+
+void pcinitlisting() {
+ // unknown args, etc
+}
+
+void pccleanuplisting(void) {
+#ifdef CW_ENABLE_PCODE_DEBUG
+ // this code is not based on the original as we don't have it
+ if (pcfile) {
+ fclose(pcfile);
+ pcfile = NULL;
+ }
+#endif
+}
+
+void pclistblocks(char *name1, char *name2) {
+#ifdef CW_ENABLE_PCODE_DEBUG
+ // this code is not based on the original as we don't have it
+ PCodeBlock *block;
+ if (copts.debuglisting) {
+ if (!pcfile)
+ pcfile = fopen("pcdump.txt", "a");
+
+ fprintf(pcfile, "\n%s\n%s\n", name1, name2);
+ for (block = pcbasicblocks; block; block = block->nextBlock)
+ pclistblock(block, NULL, 0);
+ }
+#endif
+}
+
+void pclistdataflow() {
+ // unknown args
+}
+
+void pclistinterferences(char *class_format, int regcount) {
+}
+
+void pclistspill() {
+ // unknown args
+}
+
+void pclistcopypropitem() {
+ // unknown args
+}
+
+void pclistcoalesce() {
+ // unknown args
+}
+
+void pclistusedefs() {
+ // unknown args
+}
+
+void pclistpropinfo() {
+ // unknown args
+}
+
+static void listloop() {
+ // unknown args
+}
+
+static void listloops() {
+ // unknown args
+}
+
+void pclistloops() {
+ // unknown args
+}
+
+static void listswitchtables() {
+ // unknown args
+}
+
+void pclistswitchtables() {
+ // unknown args
+}
+
+void pclistdominators() {
+ // unknown args
+}
+
+void pclistbackedge() {
+ // unknown args
+}
+
+static char *GetInterferenceFlags(IGNode *node) {
+ char *buf;
+ Boolean first;
+
+ first = 1;
+ buf = oalloc(512);
+ buf[0] = 0;
+
+ if (node->flags & fSpilled) {
+ strcat(buf, "fSpilled");
+ first = 0;
+ }
+
+ if (node->flags & fPushed) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPushed");
+ first = 0;
+ }
+
+ if (node->flags & fCoalesced) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fCoalesced");
+ first = 0;
+ }
+
+ if (node->flags & fCoalescedInto) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fCoalescedInto");
+ first = 0;
+ }
+
+ if (node->flags & fPairHigh) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPairHigh");
+ first = 0;
+ }
+
+ if (node->flags & fPairLow) {
+ if (!first)
+ strcat(buf, "|");
+ strcat(buf, "fPairLow");
+ first = 0;
+ }
+
+ if (!*buf)
+ strcat(buf, "no_flags");
+
+ return buf;
+}
+
+void pclistinterferencegraphnode() {
+ // unknown args
+}
+
+void pclistinterferencegraph() {
+ // unknown args
+}
+
+void pclistblock_scheduler() {
+ // unknown args
+}
+
+void pclistblocks_start_scheduler(char *str1, char *str2) {
+}
+
+void pclistblocks_end_scheduler(void) {
+ if (pclist_bad_operand)
+ CError_FATAL(1318);
+}
+
+static void printheapsize() {
+ // unknown args
+}
+
+void pctotalheap() {
+ // unknown args
+}
+
+void pctotalmemory() {
+ // unknown args
+}
+
+void pcmessage(char *probably_a_string, ...) {
+}
+
+int formatalias(Alias *alias, char *buf, int bufSize) {
+ char *name;
+ char *typestr;
+ int len;
+ int len2;
+
+ if (bufSize < 16)
+ return sprintf(buf, "...");
+
+ switch (alias->type) {
+ case AliasType0:
+ case AliasType1:
+ name = CMangler_GetLinkName(alias->object)->name;
+ if (!strlen(name) || name[0] < 0)
+ CError_FATAL(1458);
+
+ if (strlen(name) + 16 > bufSize)
+ return sprintf(buf, "...");
+
+ switch (alias->object->datatype) {
+ case DNONLAZYPTR:
+ typestr = "{NL}";
+ break;
+ case DDATA:
+ typestr = "{RW}";
+ break;
+ case DLOCAL:
+ typestr = "{SP}";
+ break;
+ default:
+ typestr = "";
+ }
+
+ len = sprintf(buf, "%0.*s%s", bufSize - 20, name, typestr, alias->size);
+ buf += len;
+ if (alias->type == AliasType0)
+ return len;
+
+ if (alias->offset == 0)
+ len2 = sprintf(buf, ":%d", alias->size);
+ else if (alias->offset > 0)
+ len2 = sprintf(buf, "+%d:%d", alias->offset, alias->size);
+ else
+ len2 = sprintf(buf, "-%d:%d", -alias->offset, alias->size);
+
+ return len + len2;
+
+ case AliasType2:
+ len = 0;
+
+ len2 = sprintf(buf, "{");
+ buf += len2;
+ len += len2;
+
+ len2 = sprintf(buf, "*");
+ buf += len2;
+ len += len2;
+
+ len2 = sprintf(buf, "}");
+ buf += len2;
+ len += len2;
+ return len;
+
+ default:
+ CError_FATAL(1543);
+ return 0;
+ }
+}
+
+int dumpalias(Alias *alias, int len, Boolean flag1, Boolean flag2) {
+ char *name;
+ char *typestr;
+ AliasMember *member;
+ Boolean notFirst;
+
+ if (!flag2 && alias == worst_case) {
+ fprintf(pcfile, " ALIAS = {worst_case}");
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return 0;
+ }
+
+ if (flag1) {
+ if (alias == worst_case)
+ fprintf(pcfile, "ALIAS worst_case = ");
+ else
+ fprintf(pcfile, " ALIAS = ");
+ }
+
+ switch (alias->type) {
+ case AliasType0:
+ case AliasType1:
+ name = CMangler_GetLinkName(alias->object)->name;
+ if (!strlen(name) || name[0] < 0)
+ CError_FATAL(1581);
+
+ switch (alias->object->datatype) {
+ case DNONLAZYPTR:
+ typestr = "{NL}";
+ break;
+ case DDATA:
+ typestr = "{RW}";
+ break;
+ case DLOCAL:
+ typestr = "{SP}";
+ break;
+ default:
+ typestr = "";
+ }
+
+ len += fprintf(pcfile, "%0.80s%s", name, typestr);
+
+ if (alias->type == AliasType0) {
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return len;
+ }
+
+ if (alias->offset == 0)
+ len += fprintf(pcfile, ":%d", alias->size);
+ else if (alias->offset > 0)
+ len += fprintf(pcfile, "+%d:%d", alias->offset, alias->size);
+ else
+ len += fprintf(pcfile, "-%d:%d", -alias->offset, alias->size);
+
+ if (flag1)
+ fprintf(pcfile, "\n");
+
+ return len;
+
+ case AliasType2:
+ len += fprintf(pcfile, "{");
+ notFirst = 0;
+ for (member = alias->parents; member; member = member->nextParent) {
+ if (member->child->type == AliasType0) {
+ if (notFirst)
+ len += fprintf(pcfile, ",");
+ if (len > 60) {
+ fprintf(pcfile, "\n ");
+ len = 0;
+ }
+ len = dumpalias(member->child, len, 0, 0);
+ notFirst = 1;
+ }
+ }
+ for (member = alias->parents; member; member = member->nextParent) {
+ if (member->child->type != AliasType0) {
+ if (notFirst)
+ len += fprintf(pcfile, ",");
+ if (len > 60) {
+ fprintf(pcfile, "\n ");
+ len = 0;
+ }
+ len = dumpalias(member->child, len, 0, 0);
+ notFirst = 1;
+ }
+ }
+
+ len += fprintf(pcfile, "}");
+ if (flag1)
+ fprintf(pcfile, "\n");
+ return len;
+
+ default:
+ CError_FATAL(1661);
+ return 0;
+ }
+}
+
+void pcformatset() {
+ // unknown args
+}
+
+int GetLineEndOffset(char *str, int lineNum, int len) {
+ int offset;
+ char *work;
+
+ offset = GetLineOffset(str, lineNum, len);
+ if (offset < 0)
+ return offset;
+
+ work = str + offset;
+ while (*work) {
+ if (*work == '\n')
+ return work - str - 1;
+ work++;
+ }
+ return -1;
+}
+
+int GetLineOffset(char *str, int lineNum, int len) {
+ char *work = str;
+ char *end;
+
+ if (lineNum < 0)
+ return -1;
+
+ end = str + len;
+ while (work < end) {
+ if (*work == '\n' && --lineNum <= 0)
+ return work - str;
+ work++;
+ }
+
+ return 0;
+}
+
+void DumpSourceCode() {
+ // unknown args
+}
+
+int DumpIR_SrcBreak() {
+ // unknown args
+ return 0;
+}
+
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
new file mode 100644
index 0000000..b1f8ffb
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/PCodeUtilities.c
@@ -0,0 +1,345 @@
+#include "compiler/PCodeUtilities.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/Exceptions.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/Registers.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+
+void pcsetrecordbit(PCode *pc) {
+ int reg;
+ PCodeArg *arg;
+ short argCount;
+ int argIdx;
+
+ pc->flags &= ~(fIsMove | fCommutative | fIsCSE);
+ if ((pc->flags & fOpTypeMask) == fOpTypeFPR) {
+ reg = 1;
+ } else if ((pc->flags & fOpTypeMask) == fOpTypeVR) {
+ reg = 6;
+ } else {
+ reg = 0;
+ }
+
+ if (pc->op == PC_ANDI || pc->op == PC_ANDIS) {
+ pc->flags |= fRecordBit;
+ } else if (pc->op == PC_ADDI || pc->op == PC_ADDIC) {
+ pc->flags |= fSetsCarry;
+ pc->flags |= fRecordBit;
+ change_num_operands(pc, 5);
+ pc->op = PC_ADDICR;
+
+ CError_ASSERT(76, pc->args[3].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[3].kind = PCOp_REGISTER;
+ pc->args[3].arg = RegClass_SPR;
+ pc->args[3].data.reg.reg = 0;
+ pc->args[3].data.reg.effect = EffectWrite;
+ CError_ASSERT(80, pc->args[4].kind == PCOp_PLACEHOLDEROPERAND);
+ pc->args[4].kind = PCOp_REGISTER;
+ pc->args[4].arg = RegClass_CRFIELD;
+ pc->args[4].data.reg.reg = reg;
+ pc->args[4].data.reg.effect = EffectWrite;
+ } else {
+ arg = pc->args;
+ argIdx = argCount = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_CRFIELD && arg->data.reg.reg == reg) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fRecordBit;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+ if (argIdx <= 0) {
+ arg = &pc->args[argCount];
+ pc->argCount++;
+ }
+
+ CError_ASSERT(105, arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_CRFIELD;
+ arg->data.reg.reg = reg;
+ arg->data.reg.effect = EffectWrite;
+ if (pc->op != PC_ADDICR)
+ pc->flags |= fRecordBit;
+ }
+}
+
+void pcsetsideeffects(PCode *pc) {
+ pc->flags &= ~(fIsMove | fCommutative | fIsCSE);
+ pc->flags |= fSideEffects;
+}
+
+void pcsetlinkbit(PCode *pc) {
+ PCodeArg *arg;
+ int argIdx;
+
+ switch (pc->op) {
+ case PC_B:
+ pc->op = PC_BL;
+ break;
+ case PC_BCTR:
+ pc->op = PC_BCTRL;
+ break;
+ case PC_BLR:
+ pc->op = PC_BLRL;
+ break;
+ }
+
+ arg = pc->args;
+ argIdx = pc->argCount;
+ while (arg->kind != PCOp_PLACEHOLDEROPERAND && argIdx) {
+ if (arg->kind == PCOp_REGISTER && arg->arg == RegClass_SPR && arg->data.reg.reg == 1) {
+ arg->data.reg.effect |= EffectWrite;
+ pc->flags |= fLink;
+ return;
+ }
+ arg++;
+ argIdx--;
+ }
+
+ CError_ASSERT(169, arg->kind == PCOp_PLACEHOLDEROPERAND);
+ arg->kind = PCOp_REGISTER;
+ arg->arg = RegClass_SPR;
+ arg->data.reg.reg = 1;
+ arg->data.reg.effect = EffectWrite;
+
+ if (opcodeinfo[pc->op].flags & fIsCall) {
+ pc->flags &= ~fIsBranch;
+ pc->flags |= fIsCall;
+ }
+ pc->flags |= fLink;
+}
+
+void branch_label(PCodeLabel *label) {
+ if (pclastblock->pcodeCount) {
+ pcbranch(pclastblock, label);
+ makepcblock();
+ }
+ pclabel(pclastblock, label);
+}
+
+void branch_conditional(short a, short compareop, short c, PCodeLabel *label) {
+ PCodeBlock *tmpblock;
+ PCodeLabel *tmplabel;
+ int r28;
+
+ tmpblock = pclastblock;
+ tmplabel = makepclabel();
+
+ switch (compareop) {
+ case ENOTEQU:
+ c = !c;
+ case EEQU:
+ r28 = 2;
+ break;
+ case EGREATEREQU:
+ c = !c;
+ case ELESS:
+ r28 = 0;
+ break;
+ case ELESSEQU:
+ c = !c;
+ case EGREATER:
+ r28 = 1;
+ break;
+ }
+
+ emitpcode(c ? PC_BT : PC_BF, a, r28, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_always(PCodeLabel *label) {
+ emitpcode(PC_B, label);
+ pcbranch(pclastblock, label);
+ makepcblock();
+}
+
+void branch_decrement_always(Opcode opcode, PCodeLabel *label) {
+ PCodeLabel *tmplabel = makepclabel();
+ emitpcode(opcode, label);
+ pcbranch(pclastblock, label);
+ pcbranch(pclastblock, tmplabel);
+ makepcblock();
+ pclabel(pclastblock, tmplabel);
+}
+
+void branch_indirect(Object *obj) {
+ emitpcode(PC_BCTR, obj, 0);
+ makepcblock();
+}
+
+int branch_count_volatiles(void) {
+ int count = 0;
+ int i;
+ RegClass rclass;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (i = 0; i < n_scratch_registers[rclass]; i++) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+PCodeArg *branch_record_volatiles(PCodeArg *arglist, UInt32 *masks) {
+ int i;
+ RegClass rclass;
+
+ for (rclass = RegClassMax - 1; rclass >= 0; rclass--) {
+ for (i = 0; i < n_scratch_registers[rclass]; i++) {
+ arglist->kind = PCOp_REGISTER;
+ arglist->arg = rclass;
+ arglist->data.reg.reg = scratch_registers[rclass][i];
+ arglist->data.reg.effect = EffectWrite;
+ if (masks[rclass] & (1 << scratch_registers[rclass][i]))
+ arglist->data.reg.effect |= EffectRead;
+ arglist++;
+ }
+ }
+
+ return arglist;
+}
+
+void branch_subroutine(Object *obj, short add_nop, UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BL, count, obj, 0);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ if (add_nop)
+ emitpcode(PC_NOP);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void branch_subroutine_ctr(UInt32 *masks) {
+ int count;
+ PCode *pc;
+ PCodeArg *arg;
+
+ count = branch_count_volatiles();
+ if (copts.exceptions && current_statement)
+ count += countexceptionactionregisters(current_statement->dobjstack);
+
+ pc = makepcode(PC_BCTRL, count);
+ arg = branch_record_volatiles(pc->args + 1, masks);
+ if (copts.exceptions && current_statement)
+ noteexceptionactionregisters(current_statement->dobjstack, arg);
+ appendpcode(pclastblock, pc);
+
+ branch_label(makepclabel());
+ if (copts.exceptions && current_statement)
+ recordexceptionactions(pc, current_statement->dobjstack);
+}
+
+void add_immediate(short dest_reg, short base_reg, Object *obj, SInt16 offset) {
+ short tmp_reg = base_reg;
+
+ if (obj && offset && obj->datatype != DLOCAL) {
+ tmp_reg = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(tmp_reg, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (!obj && !offset)
+ emitpcode(PC_MR, dest_reg, tmp_reg);
+ else
+ emitpcode(PC_ADDI, dest_reg, tmp_reg, obj, offset);
+}
+
+PCode *add_immediate_lo(short dest_reg, short base_reg, Object *obj, SInt16 offset, char add_to_block) {
+ PCode *pc;
+
+ CError_ASSERT(577, obj);
+
+ pc = makepcode(PC_ADDI, dest_reg, base_reg, obj, offset);
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+PCode *op_absolute_ha(short dest_reg, short base_reg, Object *obj, short offset, char add_to_block) {
+ PCode *pc;
+ int tmp_reg;
+
+ if (obj->datatype == DLOCAL) {
+ pc = makepcode(PC_ADDIS, dest_reg, base_reg, obj, offset);
+ } else if (copts.codegen_pic) {
+ tmp_reg = base_reg;
+ CError_ASSERT(601, tmp_reg);
+ pc = makepcode(PC_ADDIS, dest_reg, tmp_reg, obj, offset);
+ } else {
+ CError_ASSERT(606, base_reg == 0);
+ pc = makepcode(PC_LIS, dest_reg, obj, offset);
+ }
+
+ if (add_to_block)
+ appendpcode(pclastblock, pc);
+ return pc;
+}
+
+void load_store_register(Opcode opcode, short dest_reg, short base_reg, Object *obj, SInt32 offset) {
+ short addi_tmp;
+ short offset_reg1;
+ short offset_reg2;
+
+ offset_reg1 = base_reg;
+ if (obj && offset && obj->datatype != DLOCAL) {
+ offset_reg1 = used_virtual_registers[RegClass_GPR]++;
+ add_immediate_lo(offset_reg1, base_reg, obj, 0, 1);
+ obj = NULL;
+ }
+
+ if (offset != (short)offset) {
+ if (opcode == PC_LWZ && dest_reg == 12)
+ offset_reg2 = 12;
+ else if (opcode == PC_LWZ && dest_reg == 11)
+ offset_reg2 = 11;
+ else
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+
+ emitpcode(PC_ADDIS, offset_reg2, offset_reg1, 0, (short) ((offset >> 16) + ((offset & 0x8000) >> 15)));
+ offset = (short) offset;
+ offset_reg1 = offset_reg2;
+ }
+
+ if (opcode == PC_STVX || opcode == PC_LVX) {
+ offset_reg2 = 0;
+ if (obj) {
+ addi_tmp = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADDI, addi_tmp, offset_reg1, obj, offset);
+ offset_reg1 = addi_tmp;
+ } else if (offset) {
+ offset_reg2 = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LI, offset_reg2, offset);
+ }
+ if (!offset_reg2)
+ emitpcode(opcode, dest_reg, 0, offset_reg1);
+ else
+ emitpcode(opcode, dest_reg, offset_reg1, offset_reg2);
+ } else {
+ emitpcode(opcode, dest_reg, offset_reg1, obj, offset);
+ }
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c
new file mode 100644
index 0000000..151e448
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Peephole.c
@@ -0,0 +1,2753 @@
+#include "compiler/Peephole.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/PCode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler/Scheduler.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Alias.h"
+#include "compiler/CParser.h"
+
+typedef int (*PeepholeFunc)(PCode *instr, UInt32 *masks);
+
+typedef struct Pattern {
+ struct Pattern *next;
+ PeepholeFunc func;
+} Pattern;
+
+typedef struct LiveRegs {
+ UInt32 x0;
+ UInt32 x4;
+ UInt32 x8;
+ UInt32 xC;
+} LiveRegs;
+
+static LiveRegs *liveregs[RegClassMax];
+static Pattern *peepholepatterns[OPCODE_MAX];
+static PCode **defininginstruction;
+
+static void computeregisterusedefs(void) {
+ PCodeBlock *block;
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+ RegClass rclass;
+ LiveRegs *lr;
+ UInt32 array1[RegClassMax];
+ UInt32 array2[RegClassMax];
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ array1[rclass] = 0;
+ array2[rclass] = 0;
+ }
+
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (op->data.reg.effect & EffectRead) &&
+ !((1 << op->data.reg.reg) & array2[op->arg])
+ )
+ array1[op->arg] |= 1 << op->data.reg.reg;
+ }
+
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (op->data.reg.effect & EffectWrite) &&
+ !((1 << op->data.reg.reg) & array1[op->arg])
+ )
+ array2[op->arg] |= 1 << op->data.reg.reg;
+ }
+ }
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ lr = liveregs[rclass] + block->blockIndex;
+ lr->x0 = array1[rclass];
+ lr->x4 = array2[rclass];
+ if (rclass == RegClass_GPR) {
+ lr->x8 = 1 << 1;
+ lr->xC = 1 << 1;
+ } else {
+ lr->x8 = 0;
+ lr->xC = 0;
+ }
+ }
+ }
+}
+
+static void computeliveness(LiveRegs *lrarray, UInt32 x) {
+ PCodeBlock *block;
+ LiveRegs *lr;
+ PCLink *link;
+ UInt32 newC;
+ UInt32 new8;
+ int i;
+ int flag;
+
+ flag = 1;
+ while (flag) {
+ flag = 0;
+ i = pcblockcount;
+ while (i) {
+ if ((block = depthfirstordering[--i])) {
+ lr = lrarray + block->blockIndex;
+ newC = x;
+ for (link = block->successors; link; link = link->nextLink)
+ newC |= lrarray[link->block->blockIndex].x8;
+ lr->xC = newC;
+
+ new8 = lr->x0 | (lr->xC & ~lr->x4);
+ if (new8 != lr->x8) {
+ lr->x8 = new8;
+ flag = 1;
+ }
+ }
+ }
+ }
+}
+
+static void computeliveregisters(Object *func) {
+ Type *returntype;
+ RegClass rclass;
+
+ returntype = TYPE_FUNC(func->type)->functype;
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ liveregs[rclass] = lalloc(sizeof(LiveRegs) * pcblockcount);
+
+ computedepthfirstordering();
+ computeregisterusedefs();
+
+ if (TYPE_FITS_IN_REGISTER(returntype)) {
+ liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 3;
+ if (TYPE_IS_8BYTES(returntype))
+ liveregs[RegClass_GPR][epilogue->blockIndex].x0 |= 1 << 4;
+ } else if (IS_TYPE_FLOAT(returntype)) {
+ liveregs[RegClass_FPR][epilogue->blockIndex].x0 |= 1 << 1;
+ } else if (IS_TYPE_VECTOR(returntype)) {
+ liveregs[RegClass_VR][epilogue->blockIndex].x0 |= 1 << 2;
+ }
+
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ if (rclass == RegClass_GPR)
+ computeliveness(liveregs[rclass], 2);
+ else
+ computeliveness(liveregs[rclass], 0);
+ }
+}
+
+static void computeinstructionpredecessors(PCodeBlock *block) {
+ PCode *nop;
+ RegClass rclass;
+ SInt32 i;
+ SInt32 defID;
+ SInt32 totalOps;
+ PCode *instr;
+ PCodeArg *op;
+ PCode *array[RegClassMax][32];
+
+ nop = makepcode(PC_NOP);
+ for (rclass = 0; rclass < RegClassMax; rclass++) {
+ for (i = 0; i < 32; i++) {
+ array[rclass][i] = nop;
+ }
+ }
+
+ totalOps = 0;
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode)
+ totalOps += instr->argCount;
+
+ if (totalOps) {
+ defininginstruction = oalloc(sizeof(PCode *) * totalOps);
+ for (i = 0; i < totalOps; i++)
+ defininginstruction[i] = nop;
+
+ defID = 0;
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ instr->defID = defID;
+
+ for (i = 0, op = instr->args; i < instr->argCount; i++, op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead))
+ defininginstruction[defID + i] = array[op->arg][op->data.reg.reg];
+ }
+
+ for (i = 0, op = instr->args; i < instr->argCount; i++, op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite))
+ array[op->arg][op->data.reg.reg] = instr;
+ }
+
+ defID += instr->argCount;
+ }
+ }
+}
+
+static int dead(PCode *instr, UInt32 *masks) {
+ int i;
+ PCodeArg *op;
+
+ if (instr->block->flags & (fIsProlog | fIsEpilogue))
+ return 0;
+ if (instr->flags & (fIsBranch | fIsWrite | fIsCall | fIsVolatile | fSideEffects))
+ return 0;
+ if (!instr->block->predecessors)
+ return 1;
+
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ (op->data.reg.effect & EffectWrite) &&
+ ((1 << op->data.reg.reg) & masks[op->arg])
+ )
+ return 0;
+ }
+
+ return 1;
+}
+
+static int definedbetween(PCode *start, PCode *end, PCodeArg *checkOp) {
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+
+ for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (PC_OP_IS_WRITE_REGISTER(op, checkOp->arg, checkOp->data.reg.reg))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int usedbetween(PCode *start, PCode *end, PCodeArg *checkOp) {
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+
+ for (instr = start->prevPCode; instr != end; instr = instr->prevPCode) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (PC_OP_IS_READ_REGISTER(op, checkOp->arg, checkOp->data.reg.reg))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int isSPRlive(PCode *instr, int reg) {
+ PCode *scan;
+ PCodeArg *op;
+ int i;
+
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (PC_OP_IS_READ_REGISTER(op, RegClass_SPR, reg))
+ return 1;
+
+ if (PC_OP_IS_WRITE_REGISTER(op, RegClass_SPR, reg))
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static SInt32 extractedbits(PCode *instr) {
+ SInt32 a = instr->args[2].data.imm.value;
+ SInt32 b = instr->args[3].data.imm.value;
+ SInt32 c = instr->args[4].data.imm.value;
+ SInt32 val;
+
+ if (b <= c)
+ val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) & ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1)));
+ else
+ val = ((b > 31) ? 0 : (0xFFFFFFFFu >> b)) | ~(((c + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c + 1)));
+
+ return ((UInt32) val >> a) | (val << (32 - a));
+}
+
+static int canmergemasks(SInt32 b1, SInt32 c1, SInt32 a, SInt32 b2, SInt32 c2, short *first, short *last) {
+ SInt32 val1;
+ SInt32 val2;
+
+ if (b1 <= c1)
+ val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) & ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1)));
+ else
+ val1 = ((b1 > 31) ? 0 : (0xFFFFFFFFu >> b1)) | ~(((c1 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c1 + 1)));
+
+ if (b2 <= c2)
+ val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) & ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1)));
+ else
+ val2 = ((b2 > 31) ? 0 : (0xFFFFFFFFu >> b2)) | ~(((c2 + 1) > 31) ? 0 : (0xFFFFFFFFu >> (c2 + 1)));
+
+ return ismaskconstant(val2 & ((val1 << a) | ((UInt32) val1 >> (32 - a))), first, last);
+}
+
+static int canuseupdatetest(PCodeBlock *block, PCode *instr, int count1, int count2, int count3, int count4, int count5) {
+ int i;
+ PCLink *link;
+
+ while (instr) {
+ if (++count1 > 17)
+ return 1;
+
+ switch (instr->op) {
+ case PC_DIVW:
+ case PC_DIVWU:
+ case PC_MULHW:
+ case PC_MULHWU:
+ case PC_MULLI:
+ case PC_MULLW:
+ return count3 == 0;
+ case PC_MTXER:
+ case PC_MTCTR:
+ case PC_MTLR:
+ case PC_MTCRF:
+ case PC_MTMSR:
+ case PC_MTSPR:
+ case PC_MFMSR:
+ case PC_MFSPR:
+ case PC_MFXER:
+ case PC_MFCTR:
+ case PC_MFLR:
+ case PC_MFCR:
+ case PC_ECIWX:
+ case PC_ECOWX:
+ case PC_DCBI:
+ case PC_ICBI:
+ case PC_MCRFS:
+ case PC_MCRXR:
+ case PC_MFTB:
+ case PC_MFSR:
+ case PC_MTSR:
+ case PC_MFSRIN:
+ case PC_MTSRIN:
+ case PC_MTFSB0:
+ case PC_MTFSB1:
+ case PC_MTFSFI:
+ case PC_SC:
+ case PC_TLBIA:
+ case PC_TLBIE:
+ case PC_TLBLD:
+ case PC_TLBLI:
+ case PC_TLBSYNC:
+ case PC_TW:
+ case PC_TRAP:
+ case PC_TWI:
+ case PC_MFROM:
+ case PC_DSA:
+ case PC_ESA:
+ return 1;
+ case PC_CRAND:
+ case PC_CRANDC:
+ case PC_CREQV:
+ case PC_CRNAND:
+ case PC_CRNOR:
+ case PC_CROR:
+ case PC_CRORC:
+ case PC_CRXOR:
+ case PC_MCRF:
+ if (++count5 > 1)
+ return 1;
+ }
+
+ if (instr->flags & (fIsRead | fIsWrite)) {
+ if (++count4 > 1)
+ return 1;
+ } else if (instr->flags & fIsBranch) {
+ if (++count2 > 2)
+ return 1;
+
+ for (i = 0; i < instr->argCount; i++) {
+ if (PC_OP_IS_ANY_REGISTER(&instr->args[i], RegClass_CRFIELD)) {
+ ++count3;
+ break;
+ }
+ }
+ }
+
+ instr = instr->nextPCode;
+ }
+
+ if (block && block->successors) {
+ for (link = block->successors; link; link = link->nextLink) {
+ if (link->block && !canuseupdatetest(link->block, link->block->firstPCode, count1, count2, count3, count4, count5))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int canuseupdate(PCode *instr) {
+ return canuseupdatetest(instr->block, instr->nextPCode, 0, 0, 0, 0, 0);
+}
+
+static int MR_Rx_Rx(PCode *instr, UInt32 *masks) {
+ if (
+ instr->args[0].data.reg.reg == instr->args[1].data.reg.reg &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit)
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int FMR_Fx_Fx(PCode *instr, UInt32 *masks) {
+ if (
+ instr->args[0].data.reg.reg == instr->args[1].data.reg.reg &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit)
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int VMR_Vx_Vx(PCode *instr, UInt32 *masks) {
+ if (
+ instr->args[0].data.reg.reg == instr->args[1].data.reg.reg &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit)
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int MR_MR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_MR &&
+ instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ !definedbetween(instr, defInstr, &instr->args[0]) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit)
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int FMR_FMR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_FMR &&
+ instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int VMR_VMR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_VMR &&
+ instr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int VMR_VMRP(PCode *instr, UInt32 *masks) {
+ PCode *prev = instr->prevPCode;
+ PCode *next = instr->nextPCode;
+ int prevFlag = 0;
+ int prevPermute = 0;
+ int nextFlag = 0;
+ int nextPermute = 0;
+
+ if (prev) {
+ prevFlag = (prev->flags & fOpTypeMask) == fOpTypeVR;
+ prevPermute = uses_vpermute_unit(prev);
+ }
+ if (next) {
+ nextFlag = (next->flags & fOpTypeMask) == fOpTypeVR;
+ nextPermute = uses_vpermute_unit(next);
+ }
+
+ if (prev) {
+ if (next) {
+ if (prevFlag && !prevPermute) {
+ if (nextFlag) {
+ if (!nextPermute) {
+ change_opcode(instr, PC_VMRP);
+ return 1;
+ }
+ } else {
+ change_opcode(instr, PC_VMRP);
+ return 1;
+ }
+ }
+ } else {
+ if (prevFlag && !prevPermute) {
+ change_opcode(instr, PC_VMRP);
+ return 1;
+ }
+ }
+ } else {
+ if (next && nextFlag && !nextPermute) {
+ change_opcode(instr, PC_VMRP);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int MR_CMPI(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+ PCodeArg op;
+
+ if (
+ instr->args[0].data.reg.reg == 0 &&
+ instr->args[2].data.imm.value == 0 &&
+ (PCODE_FLAG_SET_F(defInstr) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) &&
+ !usedbetween(instr, defInstr, &instr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ if (defInstr->op == PC_ADDI) {
+ op.kind = PCOp_REGISTER;
+ op.arg = RegClass_SPR;
+ op.data.reg.reg = 0;
+ op.data.reg.effect = EffectRead | EffectWrite;
+ if (usedbetween(instr, defInstr, &op))
+ return 0;
+ }
+
+ pcsetrecordbit(defInstr);
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int EXTSB_RLWINM(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_EXTSB &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ (extractedbits(instr) & 0xFFFFFF00) == 0
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int EXTSH_RLWINM(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_EXTSH &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ (extractedbits(instr) & 0xFFFF0000) == 0
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int LBZ_RLWINM(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ (defInstr->op == PC_LBZ || defInstr->op == PC_LBZX) &&
+ instr->args[2].data.imm.value == 0 &&
+ instr->args[3].data.imm.value <= 24 &&
+ instr->args[4].data.imm.value == 31 &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0]) &&
+ !usedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg;
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int LHZ_RLWINM(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ (defInstr->op == PC_LHZ || defInstr->op == PC_LHZX) &&
+ instr->args[2].data.imm.value == 0 &&
+ instr->args[3].data.imm.value <= 16 &&
+ instr->args[4].data.imm.value == 31 &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0]) &&
+ !usedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg;
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int LHA_EXTSH(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_LHA &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0]) &&
+ !usedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg;
+ deletepcode(instr);
+ return 1;
+ }
+
+ if (
+ defInstr->op == PC_EXTSB &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit)
+ )
+ {
+ if (defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg) {
+ if (
+ !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ {
+ change_opcode(instr, PC_EXTSB);
+ deletepcode(defInstr);
+ return 1;
+ }
+ } else {
+ if (!definedbetween(instr, defInstr, &defInstr->args[1])) {
+ change_opcode(instr, PC_EXTSB);
+ instr->args[1] = defInstr->args[1];
+ } else {
+ change_opcode(instr, PC_MR);
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int ADDI_L_S(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+ SInt32 addleft;
+ SInt32 addright;
+
+ if (defInstr->op == PC_ADDI && instr->args[2].kind == PCOp_IMMEDIATE) {
+ if (!PC_OP_IS_REGISTER(&instr->args[0], RegClass_GPR, instr->args[1].data.reg.reg)) {
+ if (
+ instr->args[2].data.imm.value == 0 &&
+ defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) || canuseupdate(instr))
+ )
+ {
+ if (!(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) {
+ instr->args[2] = defInstr->args[2];
+ } else {
+ instr->op++;
+ instr->args[1].data.reg.effect |= EffectWrite;
+ instr->args[2] = defInstr->args[2];
+ }
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ addleft = 0x1FFFF;
+ addright = instr->args[2].data.imm.value;
+ if (defInstr->args[2].kind == PCOp_IMMEDIATE) {
+ addleft = defInstr->args[2].data.imm.value;
+ } else if (defInstr->args[2].kind == PCOp_MEMORY) {
+ if (defInstr->args[2].data.mem.obj->datatype == DLOCAL)
+ addleft = defInstr->args[2].data.mem.offset + defInstr->args[2].data.mem.obj->u.var.uid;
+ else if (addright == 0)
+ addleft = 0;
+ else
+ return 0;
+ }
+
+ if (!FITS_IN_SHORT(addleft + addright))
+ return 0;
+
+ if (
+ !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1])
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ if (defInstr->args[2].kind == PCOp_MEMORY) {
+ instr->args[2] = defInstr->args[2];
+ instr->args[2].data.mem.offset += addright;
+ if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) {
+ instr->alias = make_alias(
+ instr->args[2].data.mem.obj,
+ instr->args[2].data.mem.offset,
+ nbytes_loaded_or_stored_by(instr)
+ );
+ }
+ } else {
+ instr->args[2].data.imm.value = addleft + addright;
+ }
+
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ if (
+ instr->args[1].data.reg.reg != defInstr->args[1].data.reg.reg &&
+ !definedbetween(instr, defInstr, &defInstr->args[1])
+ )
+ {
+ if (defInstr->args[2].kind == PCOp_MEMORY && defInstr->args[2].data.mem.obj->datatype != DLOCAL)
+ return 0;
+
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ if (defInstr->args[2].kind == PCOp_MEMORY) {
+ instr->args[2] = defInstr->args[2];
+ instr->args[2].data.mem.offset += addright;
+ if (instr->flags & (fIsRead | fIsWrite | fPCodeFlag20000 | fPCodeFlag40000)) {
+ instr->alias = make_alias(
+ instr->args[2].data.mem.obj,
+ instr->args[2].data.mem.offset,
+ nbytes_loaded_or_stored_by(instr)
+ );
+ }
+ } else {
+ instr->args[2].data.imm.value = addleft + addright;
+ }
+
+ return 1;
+ }
+ }
+ } else {
+ if (
+ defInstr->op == PC_MR &&
+ PC_OP_IS_ANY_REGISTER(&defInstr->args[1], RegClass_GPR) &&
+ defInstr->args[1].data.reg.reg != 0 &&
+ !definedbetween(instr, defInstr, &defInstr->args[1])
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ }
+ }
+
+ return 0;
+}
+
+static int ADDI_LU_SU(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ instr->args[2].kind == PCOp_IMMEDIATE &&
+ defInstr->args[2].kind == PCOp_IMMEDIATE &&
+ defInstr->op == PC_ADDI &&
+ defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value)
+ )
+ {
+ if ((instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) == 0) {
+ instr->op--;
+ instr->args[1].data.reg.effect &= ~EffectWrite;
+ instr->args[2].data.imm.value = 0;
+ } else {
+ instr->args[2].data.imm.value += defInstr->args[2].data.imm.value;
+ }
+
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int L_S_ADDI(PCode *instr, UInt32 *masks) {
+ PCode *scan;
+ PCodeArg *op;
+ int i;
+ short reg;
+
+ if (instr->args[2].kind != PCOp_IMMEDIATE)
+ return 0;
+
+ reg = instr->args[1].data.reg.reg;
+ if (!canuseupdate(instr))
+ return 0;
+
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (PC_OP_IS_READ_REGISTER(op, RegClass_GPR, reg))
+ return 0;
+
+ if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) {
+ if (scan->op != PC_ADDI)
+ return 0;
+ if (scan->args[2].kind != PCOp_IMMEDIATE)
+ return 0;
+
+ if (
+ instr->args[2].data.imm.value == scan->args[2].data.imm.value &&
+ scan->args[0].data.reg.reg == scan->args[1].data.reg.reg &&
+ !(instr->args[0].arg == instr->args[1].arg && instr->args[0].data.reg.reg == instr->args[1].data.reg.reg)
+ )
+ {
+ if (!(masks[RegClass_GPR] & (1 << scan->args[0].data.reg.reg))) {
+ instr->args[2] = scan->args[2];
+ } else {
+ instr->op++;
+ instr->args[1].data.reg.effect |= EffectWrite;
+ instr->args[2] = scan->args[2];
+ }
+
+ change_opcode(scan, PC_NOP);
+ change_num_operands(scan, 0);
+ deletepcode(scan);
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int LI_CMP_BC(PCode *instr, UInt32 *masks) {
+ PCode *defInstr;
+ PCode *defInstr2;
+ PCLink *link;
+ PCLink **ptr;
+
+ if (instr->args[1].data.imm.value == 2) {
+ defInstr = defininginstruction[instr->defID];
+ if ((defInstr->op == PC_CMPLI || defInstr->op == PC_CMPI) && defInstr->args[0].data.reg.reg == 0) {
+ defInstr2 = defininginstruction[defInstr->defID + 1];
+ if (
+ defInstr2->op == PC_LI &&
+ defInstr2->args[1].kind == PCOp_IMMEDIATE &&
+ (instr->op == PC_BT) == (defInstr2->args[1].data.imm.value == defInstr->args[2].data.imm.value)
+ )
+ {
+ change_opcode(instr, PC_B);
+ instr->args[0] = instr->args[2];
+ change_num_operands(instr, 1);
+
+ defininginstruction[instr->defID] = defininginstruction[instr->defID + 1];
+
+ for (ptr = &instr->block->successors; (link = *ptr); ptr = &link->nextLink) {
+ if (link->block == instr->block->nextBlock) {
+ *ptr = link->nextLink;
+ break;
+ }
+ }
+
+ for (ptr = &instr->block->nextBlock->predecessors; (link = *ptr); ptr = &link->nextLink) {
+ if (link->block == instr->block) {
+ *ptr = link->nextLink;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int RLWINM_CMPLI_BC(PCode *instr, UInt32 *masks) {
+ PCode *defInstr;
+ PCode *defInstr2;
+
+ if (instr->args[1].data.imm.value == 2) {
+ defInstr = defininginstruction[instr->defID];
+ if (defInstr->op == PC_CMPLI && defInstr->args[0].data.reg.reg == 0 && defInstr->args[2].data.imm.value == 0) {
+ defInstr2 = defininginstruction[defInstr->defID + 1];
+ if (
+ (PCODE_FLAG_SET_F(defInstr2) & (fSideEffects | fCanSetRecordBit | fOpTypeGPR)) == (fCanSetRecordBit | fOpTypeGPR) &&
+ !usedbetween(defInstr, defInstr2, &defInstr->args[0]) &&
+ !definedbetween(defInstr, defInstr2, &defInstr->args[0])
+ )
+ {
+ pcsetrecordbit(defInstr2);
+ defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int LBZ_EXTSB_CMPI_BC(PCode *instr, UInt32 *masks) {
+ PCode *defInstr;
+ PCode *defInstr2;
+
+ if (instr->args[1].data.imm.value == 2) {
+ defInstr = defininginstruction[instr->defID];
+ if (
+ (
+ (defInstr->op == PC_CMPI || defInstr->op == PC_CMPLI) &&
+ defInstr->args[2].data.imm.value >= 0 &&
+ defInstr->args[2].data.imm.value <= 127
+ )
+ ||
+ (
+ (defInstr->op == PC_EXTSB || defInstr->op == PC_EXTSH) &&
+ (PCODE_FLAG_SET_F(defInstr) & fRecordBit)
+ )
+ )
+ {
+ defInstr2 = defininginstruction[defInstr->defID + 1];
+ if (
+ defInstr2->op == PC_EXTSB &&
+ defininginstruction[defInstr2->defID + 1]->op == PC_LBZ &&
+ !(masks[RegClass_GPR] & (1 << defInstr2->args[0].data.reg.reg)) &&
+ !usedbetween(instr, defInstr, &defInstr2->args[0]) &&
+ !usedbetween(defInstr, defInstr2, &defInstr2->args[0]) &&
+ !definedbetween(defInstr, defInstr2, &defInstr2->args[1])
+ )
+ {
+ defInstr->args[1].data.reg.reg = defInstr2->args[1].data.reg.reg;
+ defininginstruction[defInstr->defID + 1] = defininginstruction[defInstr2->defID + 1];
+ deletepcode(defInstr2);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int FRSP_STFS(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID];
+
+ if (
+ defInstr->op == PC_FRSP &&
+ !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ {
+ instr->args[0].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int NOT_AND(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 2];
+
+ if (
+ defInstr->op == PC_NOT &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ {
+ instr->args[2].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 2] = defininginstruction[defInstr->defID + 1];
+ change_opcode(instr, PC_ANDC);
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int LI_MR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_LI &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ {
+ change_opcode(instr, PC_LI);
+ instr->args[1] = defInstr->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int VSPLTIS_VMR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+ short opcode = defInstr->op;
+
+ if (
+ (opcode == PC_VSPLTISB || opcode == PC_VSPLTISH || opcode == PC_VSPLTISW) &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_VR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ {
+ change_opcode(instr, opcode);
+ instr->args[1] = defInstr->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int L_MR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ (defInstr->flags & fIsRead) &&
+ !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg)) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !usedbetween(instr, defInstr, &instr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg;
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int L_FMR(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ (defInstr->flags & fIsRead) &&
+ !(masks[RegClass_FPR] & (1 << defInstr->args[0].data.reg.reg)) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ !usedbetween(instr, defInstr, &instr->args[0]) &&
+ !definedbetween(instr, defInstr, &instr->args[0])
+ )
+ {
+ defInstr->args[0].data.reg.reg = instr->args[0].data.reg.reg;
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int L_S(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID];
+ SInt32 isIndexed;
+ SInt32 isFloat;
+ SInt32 isVector;
+ PCode *scan;
+ SInt32 loadSize;
+ SInt32 defInstrOffset;
+ SInt32 scanOffset;
+ SInt32 storeSize;
+
+ if (PCODE_FLAG_SET_F(instr) & (fIsVolatile | fSideEffects | fUpdatesPtr))
+ return 0;
+ if (PCODE_FLAG_SET_F(defInstr) & (fIsVolatile | fSideEffects | fUpdatesPtr))
+ return 0;
+
+ if (
+ (defInstr->flags & fIsRead) &&
+ PC_OP_IS_REGISTER(&defInstr->args[1], RegClass_GPR, instr->args[1].data.reg.reg) &&
+ defInstr->args[2].kind == instr->args[2].kind &&
+ !definedbetween(instr, defInstr, &instr->args[1])
+ )
+ {
+ if (instr->args[2].kind == PCOp_IMMEDIATE) {
+ if (instr->args[2].data.imm.value != defInstr->args[2].data.imm.value)
+ return 0;
+ } else if (instr->args[2].kind == PCOp_MEMORY) {
+ if (instr->args[2].data.mem.offset != defInstr->args[2].data.mem.offset ||
+ instr->args[2].data.mem.obj != defInstr->args[2].data.mem.obj)
+ return 0;
+ } else if (instr->args[2].kind == PCOp_REGISTER && instr->args[2].arg == RegClass_GPR) {
+ if (instr->args[2].data.reg.reg != defInstr->args[2].data.reg.reg ||
+ definedbetween(instr, defInstr, &instr->args[2]))
+ return 0;
+ } else {
+ return 0;
+ }
+
+ isIndexed = 0;
+ isFloat = 0;
+ isVector = 0;
+ switch (defInstr->op) {
+ case PC_LBZX:
+ isIndexed = 1;
+ case PC_LBZ:
+ loadSize = 1;
+ break;
+ case PC_LHZX:
+ case PC_LHAX:
+ isIndexed = 1;
+ case PC_LHZ:
+ case PC_LHA:
+ loadSize = 2;
+ break;
+ case PC_LWZX:
+ isIndexed = 1;
+ case PC_LWZ:
+ loadSize = 4;
+ break;
+ case PC_LFSX:
+ isIndexed = 1;
+ case PC_LFS:
+ isFloat = 1;
+ loadSize = 4;
+ break;
+ case PC_LFDX:
+ isIndexed = 1;
+ case PC_LFD:
+ isFloat = 1;
+ loadSize = 8;
+ break;
+ case PC_LVX:
+ case PC_LVXL:
+ isIndexed = 1;
+ isVector = 1;
+ loadSize = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ switch (instr->op) {
+ case PC_STBX:
+ if (!isIndexed) return 0;
+ case PC_STB:
+ if (isFloat) return 0;
+ if (loadSize != 1) return 0;
+ break;
+ case PC_STHX:
+ if (!isIndexed) return 0;
+ case PC_STH:
+ if (isFloat) return 0;
+ if (loadSize != 2) return 0;
+ break;
+ case PC_STWX:
+ if (!isIndexed) return 0;
+ case PC_STW:
+ if (isFloat) return 0;
+ if (loadSize != 4) return 0;
+ break;
+ case PC_STFSX:
+ if (!isIndexed) return 0;
+ case PC_STFS:
+ if (!isFloat) return 0;
+ if (loadSize != 4) return 0;
+ break;
+ case PC_STFDX:
+ if (!isIndexed) return 0;
+ case PC_STFD:
+ if (!isFloat) return 0;
+ if (loadSize != 8) return 0;
+ break;
+ case PC_STVX:
+ case PC_STVXL:
+ if (!isIndexed) return 0;
+ if (!isVector) return 0;
+ if (loadSize != 16) return 0;
+ break;
+ default:
+ return 0;
+ }
+
+ for (scan = instr->prevPCode; scan && scan != defInstr; scan = scan->prevPCode) {
+ if (scan->flags & fIsWrite) {
+ if (scan->args[1].data.reg.reg != instr->args[1].data.reg.reg)
+ return 0;
+ if (scan->args[2].kind != defInstr->args[2].kind)
+ return 0;
+
+ if (scan->args[2].kind == PCOp_MEMORY) {
+ if (instr->args[2].data.mem.obj == scan->args[2].data.mem.obj) {
+ if (instr->args[2].data.mem.offset == defInstr->args[2].data.mem.offset)
+ return 0;
+ defInstrOffset = defInstr->args[2].data.mem.offset;
+ scanOffset = scan->args[2].data.mem.offset;
+ }
+ } else if (scan->args[2].kind == PCOp_IMMEDIATE) {
+ if (instr->args[1].data.reg.reg != scan->args[1].data.reg.reg)
+ return 0;
+ if (instr->args[2].data.imm.value == scan->args[2].data.imm.value)
+ return 0;
+ defInstrOffset = defInstr->args[2].data.imm.value;
+ scanOffset = scan->args[2].data.imm.value;
+ } else {
+ return 0;
+ }
+
+ switch (scan->op) {
+ case PC_STB:
+ case PC_STBX:
+ storeSize = 1;
+ break;
+ case PC_STH:
+ case PC_STHX:
+ storeSize = 2;
+ break;
+ case PC_STW:
+ case PC_STWX:
+ case PC_STFS:
+ case PC_STFSX:
+ storeSize = 4;
+ break;
+ case PC_STFD:
+ case PC_STFDX:
+ storeSize = 8;
+ break;
+ case PC_STVX:
+ case PC_STVXL:
+ storeSize = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ if (defInstrOffset > scanOffset) {
+ if ((scanOffset + storeSize) > defInstrOffset)
+ return 0;
+ } else {
+ if ((defInstrOffset + loadSize) > scanOffset)
+ return 0;
+ }
+ }
+ }
+
+ deletepcode(instr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int RLWINM_RLWINM(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+ short start;
+ short end;
+
+ if (
+ defInstr->op == PC_RLWINM &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !(
+ defInstr->args[0].data.reg.reg == defInstr->args[1].data.reg.reg &&
+ (
+ (defInstr->args[0].data.reg.reg != instr->args[0].data.reg.reg && (masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) ||
+ usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ ) &&
+ canmergemasks(
+ defInstr->args[3].data.imm.value,
+ defInstr->args[4].data.imm.value,
+ instr->args[2].data.imm.value,
+ instr->args[3].data.imm.value,
+ instr->args[4].data.imm.value,
+ &start, &end)
+ )
+ {
+ if (instr->op == PC_RLWIMI) {
+ if (instr->args[0].data.reg.reg == defInstr->args[0].data.reg.reg)
+ return 0;
+ if (start != instr->args[3].data.imm.value || end != instr->args[4].data.imm.value)
+ return 0;
+ }
+
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ instr->args[2].data.imm.value = (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) & 31;
+ instr->args[3].data.imm.value = start;
+ instr->args[4].data.imm.value = end;
+
+ if (
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ deletepcode(defInstr);
+
+ return 1;
+ }
+
+ if (
+ defInstr->op == PC_MR &&
+ instr->op == PC_RLWINM &&
+ !definedbetween(instr, defInstr, &defInstr->args[1])
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ if (
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0])
+ )
+ deletepcode(defInstr);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int MULLI_MULLI(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_MULLI &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ FITS_IN_SHORT(instr->args[2].data.imm.value * defInstr->args[2].data.imm.value)
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ instr->args[2].data.imm.value *= defInstr->args[2].data.imm.value;
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int ADDI_ADDI(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_ADDI &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ instr->args[2].kind == PCOp_IMMEDIATE &&
+ defInstr->args[2].kind == PCOp_IMMEDIATE &&
+ FITS_IN_SHORT(instr->args[2].data.imm.value + defInstr->args[2].data.imm.value)
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ instr->args[2].data.imm.value += defInstr->args[2].data.imm.value;
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int SRAWI_SRAWI(PCode *instr, UInt32 *masks) {
+ PCode *defInstr = defininginstruction[instr->defID + 1];
+
+ if (
+ defInstr->op == PC_SRAWI &&
+ (defInstr->args[0].data.reg.reg == instr->args[0].data.reg.reg || !(masks[RegClass_GPR] & (1 << defInstr->args[0].data.reg.reg))) &&
+ !(PCODE_FLAG_SET_F(defInstr) & fRecordBit) &&
+ !definedbetween(instr, defInstr, &defInstr->args[1]) &&
+ !usedbetween(instr, defInstr, &defInstr->args[0]) &&
+ instr->args[2].kind == PCOp_IMMEDIATE &&
+ defInstr->args[2].kind == PCOp_IMMEDIATE &&
+ (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) < 32 &&
+ (instr->args[2].data.imm.value + defInstr->args[2].data.imm.value) > 0
+ )
+ {
+ instr->args[1].data.reg.reg = defInstr->args[1].data.reg.reg;
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr->defID + 1];
+
+ instr->args[2].data.imm.value += defInstr->args[2].data.imm.value;
+ deletepcode(defInstr);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int MR_ADDI(PCode *instr, UInt32 *masks) {
+ PCode *prev = instr->prevPCode;
+ PCode *next = instr->nextPCode;
+ int prevFlag = 0;
+ int nextFlag = 0;
+
+ if (copts.processor == CPU_PPC603e) {
+ if (prev)
+ prevFlag = (prev->flags & fOpTypeMask) == fOpTypeGPR;
+ if (next)
+ nextFlag = (next->flags & fOpTypeMask) == fOpTypeGPR;
+
+ if (
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ instr->argCount >= 2 &&
+ instr->args[1].data.reg.reg != 0 &&
+ (prevFlag || nextFlag)
+ )
+ {
+ change_opcode(instr, PC_ADDI);
+ instr->args[2].kind = PCOp_IMMEDIATE;
+ instr->args[2].data.imm.value = 0;
+ instr->args[2].data.imm.obj = NULL;
+ change_num_operands(instr, 3);
+ }
+ }
+
+ return 0;
+}
+
+static int rotatedefinedusedtest(UInt32 *masks, PCode *instr, PCode *a, PCode *b, PCode *subfic) {
+ PCode *scan;
+ PCodeArg *op;
+ int i;
+ int reg1;
+ int reg2;
+
+ if (
+ (masks[RegClass_GPR] & (1 << subfic->args[0].data.reg.reg)) &&
+ subfic->args[0].data.reg.reg != instr->args[0].data.reg.reg &&
+ subfic->args[0].data.reg.reg != a->args[2].data.reg.reg
+ )
+ return 1;
+
+ for (scan = instr->block->firstPCode; scan != instr->block->lastPCode; scan = scan->nextPCode) {
+ if (scan == a) break;
+ if (scan == b) break;
+ if (scan == subfic) break;
+ }
+
+ reg1 = a->args[1].data.reg.reg;
+ reg2 = subfic->args[1].data.reg.reg;
+ while (scan != instr) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (
+ op->kind == PCOp_REGISTER &&
+ op->arg == RegClass_GPR &&
+ (
+ (
+ (op->data.reg.reg == reg1 || op->data.reg.reg == reg2) &&
+ (op->data.reg.effect & EffectWrite)
+ )
+ ||
+ (
+ op->data.reg.reg == subfic->args[0].data.reg.reg && (op->data.reg.effect & EffectRead)
+ )
+ ) &&
+ scan != a &&
+ scan != b &&
+ scan != subfic
+ )
+ return 1;
+ }
+
+ scan = scan->nextPCode;
+ }
+
+ return 0;
+}
+
+static int SRW_SUBFIC_RLW_OR(PCode *instr, UInt32 *masks) {
+ PCode *subfic;
+ PCode *defInstr1 = defininginstruction[instr->defID + 1];
+ PCode *defInstr2 = defininginstruction[instr->defID + 2];
+
+ if (PCODE_FLAG_SET_F(instr) & fRecordBit)
+ return 0;
+
+ if (
+ (masks[RegClass_GPR] & (1 << instr->args[1].data.reg.reg)) &&
+ instr->args[1].data.reg.reg != instr->args[0].data.reg.reg
+ )
+ return 0;
+
+ if (
+ (masks[RegClass_GPR] & (1 << instr->args[2].data.reg.reg)) &&
+ instr->args[1].data.reg.reg != instr->args[0].data.reg.reg
+ )
+ return 0;
+
+ if (defInstr1->op != PC_SRW && defInstr1->op != PC_SLW)
+ return 0;
+ if (defInstr2->op != PC_SRW && defInstr2->op != PC_SLW)
+ return 0;
+
+ if (usedbetween(instr, defInstr1, &defInstr1->args[0]))
+ return 0;
+ if (usedbetween(instr, defInstr2, &defInstr2->args[0]))
+ return 0;
+
+ if (
+ defInstr1->op == PC_SRW && defInstr2->op == PC_SLW &&
+ defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg
+ )
+ {
+ subfic = defininginstruction[defInstr1->defID + 2];
+ if (
+ subfic->op == PC_SUBFIC &&
+ subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg &&
+ subfic->args[2].data.imm.value == 32
+ )
+ {
+ if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic))
+ return 0;
+
+ change_opcode(instr, PC_RLWNM);
+
+ instr->args[1] = defInstr1->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1];
+
+ instr->args[2] = defInstr2->args[2];
+ defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2];
+
+ instr->args[3].kind = PCOp_IMMEDIATE;
+ instr->args[3].data.imm.value = 0;
+ instr->args[3].data.imm.obj = NULL;
+
+ instr->args[4].kind = PCOp_IMMEDIATE;
+ instr->args[4].data.imm.value = 31;
+ instr->args[4].data.imm.obj = NULL;
+
+ deletepcode(defInstr1);
+ deletepcode(defInstr2);
+ deletepcode(subfic);
+ return 1;
+ }
+
+ subfic = defininginstruction[defInstr2->defID + 2];
+ if (
+ subfic->op == PC_SUBFIC &&
+ subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg &&
+ subfic->args[2].data.imm.value == 32
+ )
+ {
+ if (rotatedefinedusedtest(masks, instr, defInstr2, defInstr1, subfic))
+ return 0;
+
+ change_opcode(instr, PC_RLWNM);
+
+ instr->args[1] = defInstr1->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1];
+
+ instr->args[2] = defInstr2->args[2];
+ defininginstruction[instr->defID + 2] = defininginstruction[defInstr2->defID + 2];
+
+ instr->args[3].kind = PCOp_IMMEDIATE;
+ instr->args[3].data.imm.value = 0;
+ instr->args[3].data.imm.obj = NULL;
+
+ instr->args[4].kind = PCOp_IMMEDIATE;
+ instr->args[4].data.imm.value = 31;
+ instr->args[4].data.imm.obj = NULL;
+
+ deletepcode(defInstr1);
+ deletepcode(defInstr2);
+ return 1;
+ }
+ } else if (
+ defInstr1->op == PC_SLW && defInstr2->op == PC_SRW &&
+ defInstr1->args[1].data.reg.reg == defInstr2->args[1].data.reg.reg
+ )
+ {
+ subfic = defininginstruction[defInstr1->defID + 2];
+ if (
+ subfic->op == PC_SUBFIC &&
+ subfic->args[1].data.reg.reg == defInstr2->args[2].data.reg.reg &&
+ subfic->args[2].data.imm.value == 32
+ )
+ {
+ if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic))
+ return 0;
+
+ change_opcode(instr, PC_RLWNM);
+
+ instr->args[1] = defInstr1->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1];
+
+ instr->args[2] = defInstr1->args[2];
+ defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2];
+
+ instr->args[3].kind = PCOp_IMMEDIATE;
+ instr->args[3].data.imm.value = 0;
+ instr->args[3].data.imm.obj = NULL;
+
+ instr->args[4].kind = PCOp_IMMEDIATE;
+ instr->args[4].data.imm.value = 31;
+ instr->args[4].data.imm.obj = NULL;
+
+ deletepcode(defInstr1);
+ deletepcode(defInstr2);
+ return 1;
+ }
+
+ subfic = defininginstruction[defInstr2->defID + 2];
+ if (
+ subfic->op == PC_SUBFIC &&
+ subfic->args[1].data.reg.reg == defInstr1->args[2].data.reg.reg &&
+ subfic->args[2].data.imm.value == 32
+ )
+ {
+ if (rotatedefinedusedtest(masks, instr, defInstr1, defInstr2, subfic))
+ return 0;
+
+ change_opcode(instr, PC_RLWNM);
+
+ instr->args[1] = defInstr1->args[1];
+ defininginstruction[instr->defID + 1] = defininginstruction[defInstr1->defID + 1];
+
+ instr->args[2] = defInstr1->args[2];
+ defininginstruction[instr->defID + 2] = defininginstruction[defInstr1->defID + 2];
+
+ instr->args[3].kind = PCOp_IMMEDIATE;
+ instr->args[3].data.imm.value = 0;
+ instr->args[3].data.imm.obj = NULL;
+
+ instr->args[4].kind = PCOp_IMMEDIATE;
+ instr->args[4].data.imm.value = 31;
+ instr->args[4].data.imm.obj = NULL;
+
+ deletepcode(defInstr1);
+ deletepcode(defInstr2);
+ deletepcode(subfic);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int RLWINM_RLWIMI_STW(PCode *instr, UInt32 *masks) {
+ PCode *newInstr;
+ Boolean isZeroOffset;
+ int flags;
+ PCode *scan;
+ int i;
+ PCode *array[4];
+
+ flags = 0;
+ isZeroOffset = 0;
+ if (instr->op == PC_STW && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0)
+ isZeroOffset = 1;
+
+ scan = instr;
+ for (i = 0; i < 4; i++) {
+ if (scan->op == PC_RLWINM)
+ array[i] = defininginstruction[scan->defID + 1];
+ else
+ array[i] = defininginstruction[scan->defID];
+
+ scan = array[i];
+ if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg)
+ return 0;
+
+ if (i < 3) {
+ if (scan->op != PC_RLWIMI)
+ return 0;
+ } else {
+ if (scan->op != PC_RLWINM)
+ return 0;
+ }
+
+ if (scan->args[2].data.imm.value == 8) {
+ if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) {
+ if (flags & 1)
+ return 0;
+ flags |= 1;
+ } else if (scan->args[3].data.imm.value == 8 && scan->args[4].data.imm.value == 15) {
+ if (flags & 4)
+ return 0;
+ flags |= 4;
+ } else {
+ return 0;
+ }
+ } else if (scan->args[2].data.imm.value == 24) {
+ if (scan->args[3].data.imm.value == 0 && scan->args[4].data.imm.value == 7) {
+ if (flags & 8)
+ return 0;
+ flags |= 8;
+ } else if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) {
+ if (flags & 2)
+ return 0;
+ flags |= 2;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ if (definedbetween(instr, array[3], &array[0]->args[1]))
+ return 0;
+
+ if (instr->op == PC_STWX) {
+ change_opcode(instr, PC_STWBRX);
+ instr->args[0] = array[0]->args[1];
+ defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1];
+ return 1;
+ }
+
+ if (instr->op == PC_STW) {
+ if (!isZeroOffset) {
+ if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg))
+ return 0;
+
+ if (usedbetween(array[2], array[3], &array[0]->args[0]))
+ return 0;
+ if (usedbetween(array[1], array[2], &array[0]->args[0]))
+ return 0;
+ if (usedbetween(array[0], array[1], &array[0]->args[0]))
+ return 0;
+ if (usedbetween(instr, array[0], &array[0]->args[0]))
+ return 0;
+ }
+
+ defininginstruction[instr->defID] = defininginstruction[array[3]->defID + 1];
+
+ if (!isZeroOffset) {
+ newInstr = makepcode(PC_STWBRX, array[3]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg);
+ newInstr->alias = instr->alias;
+ change_opcode(instr, PC_ADDI);
+ insertpcodeafter(instr, newInstr);
+
+ masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg;
+ masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg;
+ instr->args[0].data.reg.effect &= ~EffectRead;
+ instr->args[0].data.reg.effect |= EffectWrite;
+ defininginstruction[instr->defID] = instr;
+
+ deletepcode(array[0]);
+ deletepcode(array[1]);
+ deletepcode(array[2]);
+ deletepcode(array[3]);
+ } else {
+ change_opcode(instr, PC_STWBRX);
+ instr->args[0] = array[0]->args[1];
+ instr->args[2] = instr->args[1];
+ defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1];
+
+ instr->args[1].kind = PCOp_REGISTER;
+ instr->args[1].arg = RegClass_GPR;
+ instr->args[1].data.reg.reg = 0;
+ instr->args[1].data.reg.effect = 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int RLWINM_RLWIMI_STH(PCode *instr, UInt32 *masks) {
+ PCode *newInstr;
+ Boolean isZeroOffset;
+ int flags;
+ PCode *scan;
+ int i;
+ PCode *array[2];
+
+ flags = 0;
+ isZeroOffset = 0;
+ if (instr->op == PC_STH && instr->args[2].kind == PCOp_IMMEDIATE && instr->args[2].data.imm.value == 0)
+ isZeroOffset = 1;
+
+ scan = instr;
+ for (i = 0; i < 2; i++) {
+ if (scan->op == PC_RLWINM)
+ array[i] = defininginstruction[scan->defID + 1];
+ else
+ array[i] = defininginstruction[scan->defID];
+
+ scan = array[i];
+ if (array[0]->args[1].data.reg.reg != scan->args[1].data.reg.reg)
+ return 0;
+
+ if (i < 1) {
+ if (scan->op != PC_RLWIMI)
+ return 0;
+ } else {
+ if (scan->op != PC_RLWINM)
+ return 0;
+ }
+
+ if (scan->args[2].data.imm.value == 8) {
+ if (scan->args[3].data.imm.value == 16 && scan->args[4].data.imm.value == 23) {
+ if (flags & 2)
+ return 0;
+ flags |= 2;
+ } else {
+ return 0;
+ }
+ } else if (scan->args[2].data.imm.value == 24) {
+ if (scan->args[3].data.imm.value == 24 && scan->args[4].data.imm.value == 31) {
+ if (flags & 1)
+ return 0;
+ flags |= 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ if (definedbetween(instr, array[1], &array[0]->args[1]))
+ return 0;
+
+ if (instr->op == PC_STHX) {
+ change_opcode(instr, PC_STHBRX);
+ instr->args[0] = array[0]->args[1];
+ defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1];
+ return 1;
+ }
+
+ if (instr->op == PC_STH) {
+ if (!isZeroOffset) {
+ if (masks[RegClass_GPR] & (1 << array[0]->args[0].data.reg.reg))
+ return 0;
+
+ if (usedbetween(array[0], array[1], &array[0]->args[0]))
+ return 0;
+ if (usedbetween(instr, array[0], &array[0]->args[0]))
+ return 0;
+ }
+
+ defininginstruction[instr->defID] = defininginstruction[array[1]->defID + 1];
+
+ if (!isZeroOffset) {
+ newInstr = makepcode(PC_STHBRX, array[1]->args[1].data.reg.reg, 0, instr->args[0].data.reg.reg);
+ newInstr->alias = instr->alias;
+ change_opcode(instr, PC_ADDI);
+
+ instr->args[0].data.reg.effect &= ~EffectRead;
+ instr->args[0].data.reg.effect |= EffectWrite;
+ defininginstruction[instr->defID] = instr;
+
+ insertpcodeafter(instr, newInstr);
+
+ masks[RegClass_GPR] |= 1 << newInstr->args[0].data.reg.reg;
+ masks[RegClass_GPR] |= 1 << newInstr->args[2].data.reg.reg;
+
+ deletepcode(array[0]);
+ deletepcode(array[1]);
+ } else {
+ change_opcode(instr, PC_STHBRX);
+ instr->args[0] = array[0]->args[1];
+ instr->args[2] = instr->args[1];
+ defininginstruction[instr->defID + 2] = defininginstruction[instr->defID + 1];
+
+ instr->args[1].kind = PCOp_REGISTER;
+ instr->args[1].arg = RegClass_GPR;
+ instr->args[1].data.reg.reg = 0;
+ instr->args[1].data.reg.effect = 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void peepholeoptimizeblock(PCodeBlock *block) {
+ RegClass rclass;
+ PCode *instr;
+ PCodeArg *op;
+ int i;
+ Pattern *pattern;
+ UInt32 masks[RegClassMax];
+
+ for (rclass = 0; rclass < RegClassMax; rclass++)
+ masks[rclass] = liveregs[rclass][block->blockIndex].xC;
+
+ for (instr = block->lastPCode; instr; instr = instr->prevPCode) {
+ if (dead(instr, masks)) {
+ deletepcode(instr);
+ } else {
+ pattern = peepholepatterns[instr->op];
+
+ while (pattern) {
+ if (pattern->func(instr, masks)) {
+ if (!instr->block)
+ break;
+ pattern = peepholepatterns[instr->op];
+ } else {
+ pattern = pattern->next;
+ }
+ }
+
+ if (instr->block) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectWrite))
+ masks[op->arg] &= ~(1 << op->data.reg.reg);
+ }
+
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (op->kind == PCOp_REGISTER && (op->data.reg.effect & EffectRead))
+ masks[op->arg] |= 1 << op->data.reg.reg;
+ }
+ }
+ }
+ }
+}
+
+static SInt32 computepossiblemask(PCode *instr, short reg) {
+ SInt32 mask;
+ SInt32 val;
+ PCodeArg *op;
+ int i;
+
+ mask = 0xFFFFFFFF;
+ while (instr) {
+ for (op = instr->args, i = instr->argCount; i--; op++) {
+ if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg)) {
+ switch (instr->op) {
+ case PC_LBZ:
+ case PC_LBZU:
+ case PC_LBZX:
+ case PC_LBZUX:
+ mask = 0xFF;
+ break;
+
+ case PC_LHZ:
+ case PC_LHZU:
+ case PC_LHZX:
+ case PC_LHZUX:
+ mask = 0xFFFF;
+ break;
+
+ case PC_LI:
+ mask = instr->args[1].data.imm.value;
+ break;
+
+ case PC_SRAWI:
+ mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) >> instr->args[2].data.imm.value;
+ break;
+
+ case PC_RLWINM:
+ val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg);
+ mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value));
+
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value)
+ val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+ else
+ val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+
+ mask &= val;
+ break;
+
+ case PC_RLWIMI:
+ val = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg);
+ mask = (val << instr->args[2].data.imm.value) | ((UInt32) val >> (32 - instr->args[2].data.imm.value));
+
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value)
+ val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+ else
+ val = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+
+ mask &= val;
+ mask |= computepossiblemask(instr->prevPCode, instr->args[0].data.reg.reg);
+ break;
+
+ case PC_OR:
+ mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) |
+ computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg);
+ break;
+
+ case PC_ORI:
+ mask = instr->args[2].data.imm.value |
+ computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg);
+ break;
+
+ case PC_AND:
+ mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg) &
+ computepossiblemask(instr->prevPCode, instr->args[2].data.reg.reg);
+ break;
+
+ case PC_ANDI:
+ mask = instr->args[2].data.imm.value &
+ computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg);
+ break;
+
+ case PC_MR:
+ mask = computepossiblemask(instr->prevPCode, instr->args[1].data.reg.reg);
+ break;
+ }
+
+ return mask;
+ }
+ }
+ instr = instr->prevPCode;
+ }
+
+ return mask;
+}
+
+static UInt32 fillmaskholes(UInt32 mask) {
+ UInt32 oneBit;
+ UInt32 allBits;
+ UInt32 result;
+
+ oneBit = 1;
+ allBits = 0xFFFFFFFF;
+ result = 0;
+
+ if ((mask & 1) && (mask & 0x80000000)) {
+ result = 0xFFFFFFFF;
+ while ((mask & oneBit) == 1) {
+ oneBit <<= 1;
+ }
+
+ while ((mask & oneBit) == 0) {
+ result &= ~oneBit;
+ oneBit <<= 1;
+ }
+
+ return result;
+ } else {
+ while ((mask & oneBit) == 0 && (mask & allBits) != 0) {
+ oneBit <<= 1;
+ allBits <<= 1;
+ }
+ while ((mask & allBits) != 0) {
+ result |= oneBit;
+ oneBit <<= 1;
+ allBits <<= 1;
+ }
+ return result;
+ }
+}
+
+static int canuseinsert(PCode *instr1, PCode *instr2, short reg) {
+ if (computepossiblemask(instr2, reg) & fillmaskholes(computepossiblemask(instr1, instr1->args[0].data.reg.reg)))
+ return 0;
+ return 1;
+}
+
+static PCode *find_def_backwords(PCode *instr, short reg) {
+ int i;
+
+ while (instr) {
+ for (i = 0; i < instr->argCount; i++) {
+ if (PC_OP_IS_WRITE_REGISTER(&instr->args[i], RegClass_GPR, reg))
+ return instr;
+ }
+ instr = instr->prevPCode;
+ }
+
+ return NULL;
+}
+
+static void adjustforward(PCodeBlock *block) {
+ PCode *instr;
+ PCode *scan;
+ PCode *tmp;
+ PCodeArg *op;
+ int i;
+ short opcode;
+ short reg0;
+ short reg1;
+ SInt32 valA;
+ SInt32 valB;
+
+ instr = block->firstPCode;
+ while (instr) {
+ if (instr->op == PC_RLWINM) {
+ SInt32 val2;
+ SInt32 val3;
+ SInt32 val4;
+ short start;
+ short end;
+
+ short flag1 = 0;
+ short flag2 = 0;
+ reg0 = instr->args[0].data.reg.reg;
+ reg1 = instr->args[1].data.reg.reg;
+ val2 = instr->args[2].data.imm.value;
+ val3 = instr->args[3].data.imm.value;
+ val4 = instr->args[4].data.imm.value;
+
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ opcode = scan->op;
+ if (opcode == PC_RLWINM && scan->args[1].data.reg.reg == reg0) {
+ if (
+ scan->args[3].data.imm.value == val3 &&
+ scan->args[4].data.imm.value == val4 &&
+ scan->args[2].data.imm.value == 0
+ )
+ {
+ if (PCODE_FLAG_SET_F(scan) & fRecordBit) {
+ if (!flag1) {
+ pcsetrecordbit(instr);
+ change_opcode(scan, PC_MR);
+ scan->flags &= ~fRecordBit;
+ scan->flags |= fIsMove;
+ change_num_operands(scan, 2);
+ } else {
+ change_opcode(scan, PC_MR);
+ scan->args[2] = scan->args[5];
+ change_num_operands(scan, 3);
+ }
+ } else {
+ change_opcode(scan, PC_MR);
+ change_num_operands(scan, 2);
+ }
+ }
+ else if (
+ reg0 != reg1 &&
+ !flag2 &&
+ canmergemasks(
+ val3,
+ val4,
+ scan->args[2].data.imm.value,
+ scan->args[3].data.imm.value,
+ scan->args[4].data.imm.value,
+ &start, &end)
+ )
+ {
+ scan->args[1].data.reg.reg = reg1;
+ scan->args[2].data.imm.value = (scan->args[2].data.imm.value + instr->args[2].data.imm.value) & 31;
+ scan->args[3].data.imm.value = start;
+ scan->args[4].data.imm.value = end;
+ }
+ }
+ else if (
+ opcode == PC_SRAWI &&
+ scan->args[1].data.reg.reg == reg0 &&
+ reg0 != reg1 &&
+ instr->args[2].data.imm.value == 0 &&
+ !(computepossiblemask(instr, reg0) & 0x80000000) &&
+ !flag2 &&
+ canmergemasks(val3, val4, 32 - scan->args[2].data.imm.value, scan->args[2].data.imm.value, 31, &start, &end) &&
+ !isSPRlive(scan, 0)
+ )
+ {
+ insertpcodeafter(scan, makepcode(
+ PC_RLWINM, scan->args[0].data.reg.reg, reg1,
+ 32 - scan->args[2].data.imm.value, start, end
+ ));
+ if (PCODE_FLAG_SET_F(scan) & fRecordBit)
+ pcsetrecordbit(scan->nextPCode);
+ deletepcode(scan);
+ }
+ else if (
+ opcode == PC_OR &&
+ !flag2 &&
+ reg0 != reg1 &&
+ !(PCODE_FLAG_SET_F(scan) & fRecordBit) &&
+ !(PCODE_FLAG_SET_F(instr) & fRecordBit) &&
+ scan->args[0].data.reg.reg != instr->args[1].data.reg.reg
+ )
+ {
+ if (scan->args[1].data.reg.reg == reg0 && canuseinsert(instr, scan, scan->args[2].data.reg.reg)) {
+ op = &scan->args[2];
+ tmp = find_def_backwords(scan->prevPCode, scan->args[2].data.reg.reg);
+ if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) {
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value)
+ valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+ else
+ valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+
+ if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value)
+ valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1)));
+ else
+ valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1)));
+
+ if (valA == ~valB)
+ op = &tmp->args[1];
+ }
+
+ change_opcode(scan, PC_MR);
+ scan->args[1] = *op;
+ change_num_operands(scan, 2);
+
+ tmp = copypcode(instr);
+ change_opcode(tmp, PC_RLWIMI);
+ tmp->args[0] = scan->args[0];
+ tmp->args[0].data.reg.effect |= EffectRead;
+
+ if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) {
+ tmp->args[3].data.imm.value = start;
+ tmp->args[4].data.imm.value = end;
+ }
+
+ insertpcodeafter(scan, tmp);
+ break;
+ }
+
+ if (
+ scan->args[2].data.reg.reg == reg0 &&
+ canuseinsert(instr, scan, scan->args[1].data.reg.reg)
+ )
+ {
+ op = &scan->args[1];
+ tmp = find_def_backwords(scan->prevPCode, scan->args[1].data.reg.reg);
+ if (tmp->op == PC_RLWINM && tmp->args[2].data.imm.value == 0) {
+ if (instr->args[3].data.imm.value <= instr->args[4].data.imm.value)
+ valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) & ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+ else
+ valA = ((instr->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> instr->args[3].data.imm.value)) | ~(((instr->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (instr->args[4].data.imm.value + 1)));
+
+ if (tmp->args[3].data.imm.value <= tmp->args[4].data.imm.value)
+ valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) & ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1)));
+ else
+ valB = ((tmp->args[3].data.imm.value > 31) ? 0 : (0xFFFFFFFFu >> tmp->args[3].data.imm.value)) | ~(((tmp->args[4].data.imm.value + 1) > 31) ? 0 : (0xFFFFFFFFu >> (tmp->args[4].data.imm.value + 1)));
+
+ if (valA == ~valB)
+ op = &tmp->args[1];
+ }
+
+ change_opcode(scan, PC_MR);
+ scan->args[1] = *op;
+ change_num_operands(scan, 2);
+
+ tmp = copypcode(instr);
+ change_opcode(tmp, PC_RLWIMI);
+ tmp->args[0] = scan->args[0];
+ tmp->args[0].data.reg.effect |= EffectRead;
+
+ if (ismaskconstant(fillmaskholes(computepossiblemask(instr, instr->args[0].data.reg.reg)), &start, &end)) {
+ tmp->args[3].data.imm.value = start;
+ tmp->args[4].data.imm.value = end;
+ }
+
+ insertpcodeafter(scan, tmp);
+ break;
+ }
+ }
+ else if (
+ !flag2 &&
+ reg0 != reg1 &&
+ val4 == 31 &&
+ instr->args[2].data.imm.value == 0 &&
+ (
+ ((opcode == PC_STB || opcode == PC_STBX) && val3 <= 24) ||
+ ((opcode == PC_STH || opcode == PC_STHX) && val3 <= 16)
+ ) &&
+ scan->args[0].data.reg.reg == reg0
+ )
+ {
+ scan->args[0].data.reg.reg = reg1;
+ }
+ else if (
+ opcode == PC_EXTSH &&
+ scan->args[1].data.reg.reg == reg0 &&
+ val2 == 0 &&
+ val3 > 16 &&
+ val3 < val4
+ )
+ {
+ change_opcode(scan, PC_MR);
+ if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) {
+ pcsetrecordbit(instr);
+ scan->flags &= ~fRecordBit;
+ scan->flags |= fIsMove;
+ change_num_operands(scan, 2);
+ }
+ }
+ else if (
+ opcode == PC_EXTSB &&
+ scan->args[1].data.reg.reg == reg0 &&
+ val2 == 0 &&
+ val3 > 24 &&
+ val3 < val4
+ )
+ {
+ change_opcode(scan, PC_MR);
+ if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag1) {
+ pcsetrecordbit(instr);
+ scan->flags &= ~fRecordBit;
+ scan->flags |= fIsMove;
+ change_num_operands(scan, 2);
+ }
+ }
+
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg0)) {
+ scan = block->lastPCode;
+ break;
+ }
+
+ if (PC_OP_IS_WRITE_REGISTER(op, RegClass_GPR, reg1))
+ flag2 = 1;
+
+ if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0))
+ flag1 = 1;
+ }
+ }
+
+ } else if (
+ instr->op == PC_EXTSB &&
+ (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg)
+ )
+ {
+ short flag = 0;
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ if (
+ (scan->op >= PC_STB && scan->op <= PC_STBUX) &&
+ scan->args[0].data.reg.reg == reg0
+ )
+ {
+ scan->args[0].data.reg.reg = reg1;
+ }
+ else if (
+ (scan->op == PC_EXTSH || scan->op == PC_EXTSB) &&
+ scan->args[1].data.reg.reg == reg0
+ )
+ {
+ change_opcode(scan, PC_MR);
+ if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) {
+ pcsetrecordbit(instr);
+ scan->flags &= ~fRecordBit;
+ scan->flags |= fIsMove;
+ change_num_operands(scan, 2);
+ }
+ }
+
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (
+ PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) &&
+ (op->data.reg.reg == reg0 || op->data.reg.reg == reg1)
+ )
+ {
+ scan = block->lastPCode;
+ break;
+ }
+
+ if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0))
+ flag = 1;
+ }
+ }
+ } else if (
+ instr->op == PC_EXTSH &&
+ (reg0 = instr->args[0].data.reg.reg) != (reg1 = instr->args[1].data.reg.reg)
+ )
+ {
+ short flag = 0;
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ if (
+ ((scan->op >= PC_STB && scan->op <= PC_STBUX) || (scan->op >= PC_STH && scan->op <= PC_STHUX)) &&
+ scan->args[0].data.reg.reg == reg0
+ )
+ {
+ scan->args[0].data.reg.reg = reg1;
+ }
+ else if (scan->op == PC_EXTSH && scan->args[1].data.reg.reg == reg0)
+ {
+ change_opcode(scan, PC_MR);
+ if ((PCODE_FLAG_SET_F(scan) & fRecordBit) && !flag) {
+ pcsetrecordbit(instr);
+ scan->flags &= ~fRecordBit;
+ scan->flags |= fIsMove;
+ change_num_operands(scan, 2);
+ }
+ }
+
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (
+ PC_OP_IS_WRITE_ANY_REGISTER(op, RegClass_GPR) &&
+ (op->data.reg.reg == reg0 || op->data.reg.reg == reg1)
+ )
+ {
+ scan = block->lastPCode;
+ break;
+ }
+
+ if (PC_OP_IS_REGISTER(op, RegClass_CRFIELD, 0))
+ flag = 1;
+ }
+ }
+ } else if (
+ instr->op == PC_ADDI &&
+ (reg0 = instr->args[0].data.reg.reg) == (reg1 = instr->args[1].data.reg.reg) &&
+ instr->args[2].kind == PCOp_IMMEDIATE
+ )
+ {
+ Boolean flag1 = 0;
+ Boolean flag2 = 0;
+ SInt32 val2 = instr->args[2].data.imm.value;
+
+ for (scan = instr->nextPCode; scan; scan = scan->nextPCode) {
+ if ((scan->flags & fIsWrite) && scan->args[0].data.reg.reg == reg0)
+ break;
+
+ if (
+ (scan->flags & (fIsRead | fIsWrite)) &&
+ scan->args[1].data.reg.reg == reg0 &&
+ scan->args[2].kind == PCOp_IMMEDIATE &&
+ FITS_IN_SHORT(val2 + scan->args[2].data.imm.value)
+ )
+ {
+ scan->args[2].data.imm.value += val2;
+ tmp = instr->prevPCode;
+ if (
+ (scan->flags & fIsRead) &&
+ scan->args[0].data.reg.reg == reg0 &&
+ scan->args[0].kind == PCOp_REGISTER &&
+ scan->args[0].arg == RegClass_GPR
+ )
+ {
+ deletepcode(instr);
+ } else {
+ deletepcode(instr);
+ insertpcodeafter(scan, instr);
+ }
+ instr = tmp;
+ break;
+ }
+
+ if (
+ scan->op == PC_ADDI &&
+ scan->args[1].data.reg.reg == reg0 &&
+ scan->args[2].kind == PCOp_IMMEDIATE &&
+ FITS_IN_SHORT(val2 + scan->args[2].data.imm.value)
+ )
+ {
+ scan->args[2].data.imm.value += val2;
+ tmp = instr->prevPCode;
+ if (scan->args[0].data.reg.reg == reg0) {
+ deletepcode(instr);
+ } else {
+ deletepcode(instr);
+ insertpcodeafter(scan, instr);
+ }
+ instr = tmp;
+ break;
+ }
+
+ if (scan->flags & (fIsBranch | fIsCall)) {
+ if (flag1 && scan->prevPCode != instr) {
+ tmp = instr->prevPCode;
+ deletepcode(instr);
+ insertpcodebefore(scan, instr);
+ instr = tmp;
+ }
+ break;
+ }
+
+ for (op = scan->args, i = scan->argCount; i--; op++) {
+ if (PC_OP_IS_R_OR_W_REGISTER(op, RegClass_GPR, reg0)) {
+ if (flag1 && scan->prevPCode != instr) {
+ tmp = instr->prevPCode;
+ deletepcode(instr);
+ insertpcodebefore(scan, instr);
+ instr = tmp;
+ }
+ flag2 = 1;
+ break;
+ }
+ }
+
+ if (flag2)
+ break;
+
+ if (scan->op != PC_ADDI)
+ flag1 = 1;
+
+ if (flag1 && !scan->nextPCode) {
+ tmp = instr->prevPCode;
+ deletepcode(instr);
+ appendpcode(block, instr);
+ instr = tmp;
+ break;
+ }
+ }
+ }
+
+ if (instr)
+ instr = instr->nextPCode;
+ else
+ instr = block->firstPCode;
+ }
+}
+
+static void installpattern(Opcode opcode, PeepholeFunc func) {
+ Pattern *pattern = lalloc(sizeof(Pattern));
+ pattern->func = func;
+ pattern->next = peepholepatterns[opcode];
+ peepholepatterns[opcode] = pattern;
+}
+
+static void installpeepholepatterns(void) {
+ int i;
+
+ for (i = 0; i < OPCODE_MAX; i++)
+ peepholepatterns[i] = NULL;
+
+ installpattern(PC_AND, NOT_AND);
+ installpattern(PC_MR, LI_MR);
+ installpattern(PC_MR, L_MR);
+ installpattern(PC_FMR, L_FMR);
+ installpattern(PC_MR, MR_MR);
+ installpattern(PC_MR, MR_Rx_Rx);
+ installpattern(PC_FMR, FMR_FMR);
+ installpattern(PC_FMR, FMR_Fx_Fx);
+ installpattern(PC_VMR, VMR_VMRP);
+ installpattern(PC_VMR, VMR_VMR);
+ installpattern(PC_VMR, VMR_Vx_Vx);
+ installpattern(PC_VMR, VSPLTIS_VMR);
+ installpattern(PC_CMPI, MR_CMPI);
+ installpattern(PC_RLWIMI, RLWINM_RLWINM);
+ installpattern(PC_RLWINM, RLWINM_RLWINM);
+ installpattern(PC_RLWINM, EXTSB_RLWINM);
+ installpattern(PC_RLWINM, EXTSH_RLWINM);
+ installpattern(PC_RLWINM, LBZ_RLWINM);
+ installpattern(PC_RLWINM, LHZ_RLWINM);
+ installpattern(PC_EXTSH, LHA_EXTSH);
+ installpattern(PC_STW, RLWINM_RLWIMI_STW);
+ installpattern(PC_STWX, RLWINM_RLWIMI_STW);
+ installpattern(PC_STH, RLWINM_RLWIMI_STH);
+ installpattern(PC_STHX, RLWINM_RLWIMI_STH);
+ installpattern(PC_LBZ, ADDI_L_S);
+ installpattern(PC_LHZ, ADDI_L_S);
+ installpattern(PC_LHA, ADDI_L_S);
+ installpattern(PC_LWZ, ADDI_L_S);
+ installpattern(PC_STB, ADDI_L_S);
+ installpattern(PC_STH, ADDI_L_S);
+ installpattern(PC_STW, ADDI_L_S);
+ installpattern(PC_LFS, ADDI_L_S);
+ installpattern(PC_LFD, ADDI_L_S);
+ installpattern(PC_STFS, ADDI_L_S);
+ installpattern(PC_STFD, ADDI_L_S);
+ installpattern(PC_LBZU, ADDI_LU_SU);
+ installpattern(PC_LHZU, ADDI_LU_SU);
+ installpattern(PC_LHAU, ADDI_LU_SU);
+ installpattern(PC_LWZU, ADDI_LU_SU);
+ installpattern(PC_STBU, ADDI_LU_SU);
+ installpattern(PC_STHU, ADDI_LU_SU);
+ installpattern(PC_STWU, ADDI_LU_SU);
+ installpattern(PC_LFSU, ADDI_LU_SU);
+ installpattern(PC_LFDU, ADDI_LU_SU);
+ installpattern(PC_STFSU, ADDI_LU_SU);
+ installpattern(PC_STFDU, ADDI_LU_SU);
+ installpattern(PC_LBZ, L_S_ADDI);
+ installpattern(PC_LHZ, L_S_ADDI);
+ installpattern(PC_LHA, L_S_ADDI);
+ installpattern(PC_LWZ, L_S_ADDI);
+ installpattern(PC_STB, L_S_ADDI);
+ installpattern(PC_STH, L_S_ADDI);
+ installpattern(PC_STW, L_S_ADDI);
+ installpattern(PC_LFS, L_S_ADDI);
+ installpattern(PC_LFD, L_S_ADDI);
+ installpattern(PC_STFS, L_S_ADDI);
+ installpattern(PC_STFD, L_S_ADDI);
+ installpattern(PC_STB, L_S);
+ installpattern(PC_STH, L_S);
+ installpattern(PC_STW, L_S);
+ installpattern(PC_STFS, L_S);
+ installpattern(PC_STFD, L_S);
+ installpattern(PC_STBX, L_S);
+ installpattern(PC_STHX, L_S);
+ installpattern(PC_STWX, L_S);
+ installpattern(PC_STFSX, L_S);
+ installpattern(PC_STFDX, L_S);
+ installpattern(PC_BT, LBZ_EXTSB_CMPI_BC);
+ installpattern(PC_BF, LBZ_EXTSB_CMPI_BC);
+ installpattern(PC_BT, RLWINM_CMPLI_BC);
+ installpattern(PC_BF, RLWINM_CMPLI_BC);
+ installpattern(PC_BT, LI_CMP_BC);
+ installpattern(PC_BF, LI_CMP_BC);
+ installpattern(PC_RLWINM, RLWINM_RLWINM);
+ installpattern(PC_MULLI, MULLI_MULLI);
+ installpattern(PC_ADDI, ADDI_ADDI);
+ installpattern(PC_SRAWI, SRAWI_SRAWI);
+ installpattern(PC_MR, MR_ADDI);
+ installpattern(PC_OR, SRW_SUBFIC_RLW_OR);
+}
+
+void peepholeoptimizeforward(Object *func) {
+ PCodeBlock *block;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (block->pcodeCount >= 2)
+ adjustforward(block);
+ }
+}
+
+void peepholemergeblocks(Object *func, Boolean flag) {
+ PCodeBlock *block;
+ PCodeBlock *next;
+ Boolean flag2;
+ PCode *instr;
+ PCode *nextinstr;
+ PCLink *link;
+ PCLink *link2;
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ flag2 = 0;
+ next = block->nextBlock;
+
+ if (!flag) {
+ flag2 = next && (next->flags & fIsEpilogue);
+ if (block->flags & fIsProlog)
+ continue;
+ }
+
+ if (block->pcodeCount > 0) {
+ for (instr = block->firstPCode; instr; instr = instr->nextPCode) {
+ if (instr->flags & (fIsCall | fSideEffects))
+ break;
+ }
+
+ if (instr)
+ continue;
+
+ instr = block->lastPCode;
+ if (instr && instr->op == PC_B) {
+ if (instr->args[0].kind == PCOp_LABEL && instr->args[0].data.label.label->block == next)
+ deletepcode(instr);
+ else
+ continue;
+ }
+
+ instr = block->lastPCode;
+ if (instr && (instr->flags & fIsBranch) && instr->op != PC_B)
+ continue;
+
+ while (
+ block->successors->block == next &&
+ block->successors->nextLink == NULL &&
+ next->predecessors->block == block &&
+ next->predecessors->nextLink == NULL &&
+ !flag2 &&
+ !(next->flags & fPCBlockFlag8000) &&
+ (block->pcodeCount + next->pcodeCount) <= 100
+ )
+ {
+ if (next->pcodeCount > 0) {
+ for (instr = next->firstPCode; instr; instr = nextinstr) {
+ nextinstr = instr->nextPCode;
+ if (instr->flags & (fIsCall | fSideEffects))
+ break;
+
+ deletepcode(instr);
+ if (instr->op != PC_B) {
+ appendpcode(block, instr);
+ } else if (instr->args[0].kind == PCOp_LABEL) {
+ if (instr->args[0].data.label.label->block != next->nextBlock)
+ appendpcode(block, instr);
+ } else {
+ appendpcode(block, instr);
+ }
+ }
+ }
+
+ if (next->pcodeCount != 0)
+ break;
+ if (next == epilogue)
+ break;
+
+ block->successors = next->successors;
+
+ for (link = block->successors; link; link = link->nextLink) {
+ for (link2 = link->block->predecessors; link2; link2 = link2->nextLink) {
+ if (link2->block == next) {
+ link2->block = block;
+ break;
+ }
+ }
+ }
+
+ block->nextBlock = next->nextBlock;
+ if (block->nextBlock)
+ block->nextBlock->prevBlock = block;
+
+ next->flags |= fDeleted;
+ next = block->nextBlock;
+
+ if (!flag)
+ flag2 = next && (next->flags & fIsEpilogue);
+ }
+ }
+ }
+}
+
+void peepholeoptimizepcode(Object *func) {
+ PCodeBlock *block;
+
+ installpeepholepatterns();
+ computeliveregisters(func);
+
+ for (block = pcbasicblocks; block; block = block->nextBlock) {
+ if (block->pcodeCount >= 1) {
+ computeinstructionpredecessors(block);
+ peepholeoptimizeblock(block);
+ freeoheap();
+ }
+ }
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c
new file mode 100644
index 0000000..6fa4524
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StackFrame.c
@@ -0,0 +1,1252 @@
+#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;
+ }
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c
new file mode 100644
index 0000000..7c28b88
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/StructMoves.c
@@ -0,0 +1,792 @@
+#include "compiler/StructMoves.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/Registers.h"
+
+void make_addressable(Operand *opnd, SInt32 offset, int unusedArg) {
+ int reg;
+
+ if (opnd->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opnd);
+
+ if (opnd->optype != OpndType_IndirectGPR_ImmOffset || (opnd->immOffset + offset) > 0x7FFF) {
+ reg = used_virtual_registers[RegClass_GPR]++;
+ load_address(reg, opnd);
+ opnd->optype = OpndType_IndirectGPR_ImmOffset;
+ opnd->reg = reg;
+ opnd->object = NULL;
+ opnd->immOffset = 0;
+ }
+}
+
+static void load_displaced_address(Operand *opnd, SInt32 offset) {
+ int reg;
+
+ reg = used_virtual_registers[RegClass_GPR]++;
+ if (opnd->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(opnd);
+
+ if (opnd->optype == OpndType_IndirectGPR_ImmOffset) {
+ offset += opnd->immOffset;
+ if (!FITS_IN_SHORT(offset)) {
+ add_immediate(reg, opnd->reg, opnd->object, opnd->immOffset);
+ emitpcode(PC_ADDI, reg, reg, 0, offset - opnd->immOffset);
+ } else {
+ add_immediate(reg, opnd->reg, opnd->object, offset);
+ }
+ } else if (opnd->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(PC_ADD, reg, opnd->reg, opnd->regOffset);
+ emitpcode(PC_ADDI, reg, reg, 0, offset);
+ } else {
+ CError_FATAL(80);
+ }
+
+ opnd->optype = OpndType_IndirectGPR_ImmOffset;
+ opnd->reg = reg;
+ opnd->object = NULL;
+ opnd->immOffset = 0;
+}
+
+static void move_block_via_load_store(Operand *dst, Operand *src, SInt32 len, SInt32 align) {
+ SInt32 step;
+ SInt32 pos;
+ int floatReg;
+ int reg;
+
+ if (src->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(src);
+ if (dst->optype == OpndType_IndirectSymbol)
+ coerce_to_addressable(dst);
+
+ if (len == 8) {
+ floatReg = used_virtual_registers[RegClass_FPR]++;
+ if (src->optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(PC_LFD, floatReg, src->reg, src->object, src->immOffset);
+ setpcodeflags(src->flags);
+ } else if (src->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(PC_LFDX, floatReg, src->reg, src->regOffset);
+ setpcodeflags(src->flags);
+ } else {
+ CError_FATAL(145);
+ }
+
+ if (dst->optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(PC_STFD, floatReg, dst->reg, dst->object, dst->immOffset);
+ setpcodeflags(dst->flags);
+ } else if (dst->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(PC_STFDX, floatReg, dst->reg, dst->regOffset);
+ setpcodeflags(dst->flags);
+ } else {
+ CError_FATAL(157);
+ }
+
+ return;
+ }
+
+ if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) {
+ SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align;
+ step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2;
+ } else {
+ step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2;
+ }
+
+ if (step != len) {
+ if (dst->optype == OpndType_IndirectGPR_Indexed)
+ make_addressable(dst, len, 0);
+ if (src->optype == OpndType_IndirectGPR_Indexed)
+ make_addressable(src, len, 0);
+ }
+
+ for (pos = 0; len != 0; len -= step, pos += step) {
+ reg = used_virtual_registers[RegClass_GPR]++;
+ if (src->optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg,
+ src->reg,
+ src->object,
+ src->immOffset + pos
+ );
+ setpcodeflags(src->flags);
+ } else if (src->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(
+ (step == 1) ? PC_LBZX : (step == 2) ? PC_LHZX : PC_LWZX,
+ reg,
+ src->reg,
+ src->regOffset
+ );
+ setpcodeflags(src->flags);
+ } else {
+ CError_FATAL(183);
+ }
+
+ if (dst->optype == OpndType_IndirectGPR_ImmOffset) {
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg,
+ dst->reg,
+ dst->object,
+ dst->immOffset + pos
+ );
+ setpcodeflags(dst->flags);
+ } else if (dst->optype == OpndType_IndirectGPR_Indexed) {
+ emitpcode(
+ (step == 1) ? PC_STBX : (step == 2) ? PC_STHX : PC_STWX,
+ reg,
+ dst->reg,
+ dst->regOffset
+ );
+ setpcodeflags(dst->flags);
+ } else {
+ CError_FATAL(195);
+ }
+ }
+}
+
+static void move_block_via_load_store_sequence(Operand *dst, Operand *src, SInt32 len, SInt32 align) {
+ SInt32 pos;
+ int i;
+ SInt32 step;
+
+ pos = 0;
+ make_addressable(dst, len, 0);
+ make_addressable(src, len, 0);
+
+ if ((align % 8) == 0) {
+ while (len >= 16) {
+ int reg1 = used_virtual_registers[RegClass_FPR]++;
+ int reg2 = used_virtual_registers[RegClass_FPR]++;
+ load_store_register(PC_LFD, reg1, src->reg, src->object, src->immOffset + pos);
+ setpcodeflags(src->flags);
+ load_store_register(PC_LFD, reg2, src->reg, src->object, src->immOffset + pos + 8);
+ setpcodeflags(src->flags);
+
+ load_store_register(PC_STFD, reg1, dst->reg, dst->object, dst->immOffset + pos);
+ setpcodeflags(dst->flags);
+ load_store_register(PC_STFD, reg2, dst->reg, dst->object, dst->immOffset + pos + 8);
+ setpcodeflags(dst->flags);
+
+ pos += 16;
+ len -= 16;
+ }
+ }
+
+ while (len >= 8) {
+ if ((align % 8) == 0) {
+ int reg = used_virtual_registers[RegClass_FPR]++;
+
+ load_store_register(PC_LFD, reg, src->reg, src->object, src->immOffset + pos);
+ setpcodeflags(src->flags);
+
+ load_store_register(PC_STFD, reg, dst->reg, dst->object, dst->immOffset + pos);
+ setpcodeflags(dst->flags);
+
+ pos += 8;
+ len -= 8;
+ } else {
+ if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) {
+ SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align;
+ step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp > 2) ? 2 : 1;
+ } else {
+ step = 4;
+ }
+
+ for (i = 0; i < 8; i += (step * 2)) {
+ int reg1 = used_virtual_registers[RegClass_GPR]++;
+ int reg2 = used_virtual_registers[RegClass_GPR]++;
+
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg1,
+ src->reg,
+ src->object,
+ src->immOffset + pos
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg2,
+ src->reg,
+ src->object,
+ src->immOffset + pos + step
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg1,
+ dst->reg,
+ dst->object,
+ dst->immOffset + pos
+ );
+ setpcodeflags(dst->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg2,
+ dst->reg,
+ dst->object,
+ dst->immOffset + pos + step
+ );
+ setpcodeflags(dst->flags);
+
+ pos += (step * 2);
+ len -= (step * 2);
+ }
+ }
+ }
+
+ while (len) {
+ int reg;
+
+ if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) {
+ SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align;
+ step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2;
+ } else {
+ step = ((UInt32) len > 4) ? 4 : ((UInt32) len <= 2) ? len : 2;
+ }
+
+ reg = used_virtual_registers[RegClass_GPR]++;
+
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg,
+ src->reg,
+ src->object,
+ src->immOffset + pos
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg,
+ dst->reg,
+ dst->object,
+ dst->immOffset + pos
+ );
+ setpcodeflags(dst->flags);
+
+ len -= step;
+ pos += step;
+ }
+}
+
+static void move_block_via_inline_loop(Operand *dst, Operand *src, SInt32 len, SInt32 align) {
+ PCodeLabel *label; // r25
+ SInt32 pos; // r25
+ SInt32 step; // r24
+ int reg1; // r22
+ int reg2; // r23
+ SInt32 remainder; // r23
+
+ label = makepclabel();
+
+ if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) {
+ SInt32 tmp = (align == 0) ? 1 : (align > len) ? len : align;
+ step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2;
+ } else {
+ step = 4;
+ }
+
+ load_displaced_address(dst, -step);
+ load_displaced_address(src, -step);
+
+ CError_ASSERT(377, (len / step) != 0);
+
+ reg1 = used_virtual_registers[RegClass_GPR]++;
+ load_immediate(reg1, len / (step * 2));
+ emitpcode(PC_MTCTR, reg1);
+ branch_label(label);
+
+ reg1 = used_virtual_registers[RegClass_GPR]++;
+ reg2 = used_virtual_registers[RegClass_GPR]++;
+
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg1,
+ src->reg,
+ NULL,
+ step
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_LBZU : (step == 2) ? PC_LHZU : PC_LWZU,
+ reg2,
+ src->reg,
+ NULL,
+ step * 2
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg1,
+ dst->reg,
+ NULL,
+ step
+ );
+ setpcodeflags(dst->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STBU : (step == 2) ? PC_STHU : PC_STWU,
+ reg2,
+ dst->reg,
+ NULL,
+ step * 2
+ );
+ setpcodeflags(dst->flags);
+
+ branch_decrement_always(PC_BDNZ, label);
+
+ for (remainder = len & 7, pos = step; remainder != 0; remainder -= step, pos += step) {
+ int reg;
+
+ if (copts.misaligned_mem_access == 0 && (UInt32) align < 4) {
+ SInt32 tmp = (align == 0) ? 1 : (align > remainder) ? remainder : align;
+ step = ((UInt32) tmp > 4) ? 4 : ((UInt32) tmp <= 2) ? (UInt32) tmp : 2;
+ } else {
+ step = ((UInt32) remainder > 4) ? 4 : ((UInt32) remainder <= 2) ? remainder : 2;
+ }
+
+ reg = used_virtual_registers[RegClass_GPR]++;
+
+ load_store_register(
+ (step == 1) ? PC_LBZ : (step == 2) ? PC_LHZ : PC_LWZ,
+ reg,
+ src->reg,
+ NULL,
+ pos
+ );
+ setpcodeflags(src->flags);
+
+ load_store_register(
+ (step == 1) ? PC_STB : (step == 2) ? PC_STH : PC_STW,
+ reg,
+ dst->reg,
+ NULL,
+ pos
+ );
+ setpcodeflags(dst->flags);
+ }
+}
+
+void move_block(Operand *dst, Operand *src, SInt32 len, SInt32 align) {
+ Operand myDst;
+
+ myDst = *dst;
+
+ CError_ASSERT(447, myDst.optype >= OpndType_IndirectGPR_ImmOffset);
+ CError_ASSERT(449, src->optype >= OpndType_IndirectGPR_ImmOffset);
+
+ if (len == 1 || len == 2 || len == 4)
+ move_block_via_load_store(&myDst, src, len, align);
+ else if (len == 8 && align == 8)
+ move_block_via_load_store(&myDst, src, len, align);
+ else if (len <= 16 || (copts.optimizesize == 0 && len <= 64))
+ move_block_via_load_store_sequence(&myDst, src, len, align);
+ else
+ move_block_via_inline_loop(&myDst, src, len, align);
+}
+
+static void load_word_of_small_struct(short dstReg, short srcReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) {
+ short tmpReg;
+ short extra = 0;
+
+ switch (len) {
+ case 1:
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7);
+ setpcodeflags(opnd->flags);
+ break;
+ case 2:
+ case 3:
+ if (align > 1) {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset);
+ extra += 2;
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15);
+ setpcodeflags(opnd->flags);
+ } else {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1);
+ extra += 2;
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15);
+ setpcodeflags(opnd->flags);
+ }
+ if (len == 3) {
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + extra);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23);
+ setpcodeflags(opnd->flags);
+ }
+ break;
+ case 4:
+ if (align > 2) {
+ load_store_register(PC_LWZ, dstReg, srcReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ } else if (align > 1) {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWINM, dstReg, tmpReg, 16, 0, 15);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_LHZ, tmpReg, srcReg, opnd->object, offset + 2);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 16, 31);
+ setpcodeflags(opnd->flags);
+ } else {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWINM, dstReg, tmpReg, 24, 0, 7);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 1);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 16, 8, 15);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 2);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 8, 16, 23);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_LBZ, tmpReg, srcReg, opnd->object, offset + 3);
+ setpcodeflags(opnd->flags);
+ emitpcode(PC_RLWIMI, dstReg, tmpReg, 0, 24, 31);
+ setpcodeflags(opnd->flags);
+ }
+ break;
+ }
+}
+
+void load_small_block_into_reg(short dstReg, Operand *srcOpnd, Type *type, SInt32 align) {
+ short finalReg;
+ short tmpReg;
+ SInt32 absAddress;
+
+ coerce_to_addressable(srcOpnd);
+
+ if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) {
+ CError_FATAL(557);
+
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_address(tmpReg, srcOpnd);
+ srcOpnd->optype = OpndType_IndirectGPR_ImmOffset;
+ srcOpnd->reg = tmpReg;
+ srcOpnd->object = NULL;
+ srcOpnd->immOffset = 0;
+ }
+
+ if (copts.misaligned_mem_access)
+ align = 4;
+
+ switch (srcOpnd->optype) {
+ case OpndType_GPRPair:
+ return;
+ case OpndType_GPR:
+ return;
+ case OpndType_GPR_ImmOffset:
+ finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++;
+ add_immediate(finalReg, srcOpnd->reg, srcOpnd->object, srcOpnd->immOffset);
+ break;
+ case OpndType_GPR_Indexed:
+ finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_ADD, finalReg, srcOpnd->reg, srcOpnd->regOffset);
+ break;
+ case OpndType_Absolute:
+ finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++;
+ absAddress = srcOpnd->immediate;
+ if (FITS_IN_SHORT(absAddress)) {
+ emitpcode(PC_LI, finalReg, absAddress);
+ } else {
+ tmpReg = finalReg;
+ if (copts.optimizationlevel > 1 && absAddress)
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress));
+ if (absAddress)
+ emitpcode(PC_ADDI, finalReg, tmpReg, 0, LOW_PART(absAddress));
+ }
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ finalReg = dstReg ? dstReg : used_virtual_registers[RegClass_GPR]++;
+ load_word_of_small_struct(finalReg, srcOpnd->reg, srcOpnd, srcOpnd->immOffset, type->size, align);
+ break;
+ default:
+ CError_FATAL(606);
+ }
+
+ srcOpnd->optype = OpndType_GPR;
+ srcOpnd->reg = finalReg;
+}
+
+void load_small_block_into_reg_pair(short dstRegLo, short dstRegHi, Operand *srcOpnd, Type *type, SInt32 align) {
+ short finalRegLo;
+ short finalRegHi;
+ short tmpRegLo;
+ short tmpRegHi;
+ short tmpReg;
+ SInt32 absAddress;
+
+ finalRegHi = -1;
+ coerce_to_addressable(srcOpnd);
+
+ if (srcOpnd->optype == OpndType_IndirectGPR_Indexed) {
+ CError_FATAL(624);
+
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_address(tmpReg, srcOpnd);
+ srcOpnd->optype = OpndType_IndirectGPR_ImmOffset;
+ srcOpnd->reg = tmpReg;
+ srcOpnd->object = NULL;
+ srcOpnd->immOffset = 0;
+ }
+
+ if (copts.misaligned_mem_access)
+ align = 4;
+
+ switch (srcOpnd->optype) {
+ case OpndType_GPRPair:
+ if (dstRegLo != 0 && dstRegHi == 0)
+ dstRegHi = used_virtual_registers[RegClass_GPR]++;
+ if (dstRegHi != 0 && dstRegLo == 0)
+ dstRegLo = used_virtual_registers[RegClass_GPR]++;
+
+ if (srcOpnd->reg != dstRegLo || srcOpnd->regHi != dstRegHi) {
+ tmpRegLo = dstRegLo ? dstRegLo : srcOpnd->reg;
+ tmpRegHi = dstRegHi ? dstRegHi : srcOpnd->regHi;
+
+ if (tmpRegLo != srcOpnd->reg) {
+ if (tmpRegLo == srcOpnd->regHi) {
+ CError_ASSERT(657, tmpRegLo != tmpRegHi);
+ emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi);
+ emitpcode(PC_MR, tmpRegLo, srcOpnd->reg);
+ } else {
+ emitpcode(PC_MR, tmpRegLo, srcOpnd->reg);
+ if (srcOpnd->regHi != tmpRegHi)
+ emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi);
+ }
+ } else if (tmpRegHi != srcOpnd->regHi) {
+ if (tmpRegHi == srcOpnd->reg) {
+ CError_ASSERT(671, tmpRegLo != tmpRegHi);
+ emitpcode(PC_MR, tmpRegLo, srcOpnd->reg);
+ emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi);
+ } else {
+ emitpcode(PC_MR, tmpRegHi, srcOpnd->regHi);
+ if (srcOpnd->reg != tmpRegLo)
+ emitpcode(PC_MR, tmpRegLo, srcOpnd->reg);
+ }
+ }
+ }
+
+ finalRegLo = srcOpnd->reg;
+ finalRegHi = srcOpnd->regHi;
+ break;
+ case OpndType_GPR:
+ CError_FATAL(688);
+ break;
+ case OpndType_GPR_ImmOffset:
+ CError_FATAL(691);
+ break;
+ case OpndType_GPR_Indexed:
+ CError_FATAL(694);
+ break;
+ case OpndType_Absolute:
+ finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++;
+ absAddress = srcOpnd->immediate;
+ if (FITS_IN_SHORT(absAddress)) {
+ emitpcode(PC_LI, finalRegLo, absAddress);
+ } else {
+ tmpReg = finalRegLo;
+ if (copts.optimizationlevel > 1 && absAddress)
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_LIS, tmpReg, 0, HIGH_PART(absAddress));
+ if (absAddress)
+ emitpcode(PC_ADDI, finalRegLo, tmpReg, 0, LOW_PART(absAddress));
+ }
+
+ finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++;
+ if (is_unsigned(type) || absAddress >= 0)
+ load_immediate(finalRegHi, 0);
+ else
+ load_immediate(finalRegHi, -1);
+
+ break;
+ case OpndType_IndirectGPR_ImmOffset:
+ finalRegLo = dstRegLo ? dstRegLo : used_virtual_registers[RegClass_GPR]++;
+ finalRegHi = dstRegHi ? dstRegHi : used_virtual_registers[RegClass_GPR]++;
+ if (srcOpnd->reg == finalRegHi) {
+ if (srcOpnd->reg == finalRegLo) {
+ CError_FATAL(726);
+ } else {
+ load_word_of_small_struct(
+ finalRegLo, srcOpnd->reg, srcOpnd,
+ srcOpnd->immOffset + low_offset, type->size - 4, align);
+ load_word_of_small_struct(
+ finalRegHi, srcOpnd->reg, srcOpnd,
+ srcOpnd->immOffset + high_offset, 4, align);
+ }
+ } else {
+ load_word_of_small_struct(
+ finalRegHi, srcOpnd->reg, srcOpnd,
+ srcOpnd->immOffset + high_offset, 4, align);
+ load_word_of_small_struct(
+ finalRegLo, srcOpnd->reg, srcOpnd,
+ srcOpnd->immOffset + low_offset, type->size - 4, align);
+ }
+ break;
+ default:
+ CError_FATAL(737);
+ }
+
+ if (finalRegHi == -1) {
+ CError_FATAL(741);
+ } else {
+ srcOpnd->optype = OpndType_GPRPair;
+ srcOpnd->reg = finalRegLo;
+ srcOpnd->regHi = finalRegHi;
+ }
+}
+
+static void store_word_of_small_struct(short srcReg, short dstReg, Operand *opnd, SInt32 offset, SInt32 len, SInt32 align) {
+ short tmpReg;
+ short extra = 0;
+
+ switch (len) {
+ case 1:
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ break;
+ case 2:
+ case 3:
+ if (align > 1) {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset);
+ extra += 2;
+ setpcodeflags(opnd->flags);
+ } else {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1);
+ extra += 2;
+ setpcodeflags(opnd->flags);
+ }
+ if (len == 3) {
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + extra);
+ setpcodeflags(opnd->flags);
+ }
+ break;
+ case 4:
+ if (align > 2) {
+ load_store_register(PC_STW, srcReg, dstReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+ } else if (align > 1) {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 16, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STH, tmpReg, dstReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_STH, srcReg, dstReg, opnd->object, offset + 2);
+ setpcodeflags(opnd->flags);
+ } else {
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 8, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset);
+ setpcodeflags(opnd->flags);
+
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 16, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 1);
+ setpcodeflags(opnd->flags);
+
+ emitpcode(PC_RLWINM, tmpReg, srcReg, 24, 24, 31);
+ setpcodeflags(opnd->flags);
+ load_store_register(PC_STB, tmpReg, dstReg, opnd->object, offset + 2);
+ setpcodeflags(opnd->flags);
+
+ load_store_register(PC_STB, srcReg, dstReg, opnd->object, offset + 3);
+ setpcodeflags(opnd->flags);
+ }
+ break;
+ }
+}
+
+void store_small_block_from_reg(short srcReg, Operand *dstOpnd, Type *type, SInt32 align) {
+ short tmpReg;
+
+ coerce_to_addressable(dstOpnd);
+
+ if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) {
+ CError_FATAL(839);
+
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_address(tmpReg, dstOpnd);
+ dstOpnd->optype = OpndType_IndirectGPR_ImmOffset;
+ dstOpnd->reg = tmpReg;
+ dstOpnd->object = NULL;
+ dstOpnd->immOffset = 0;
+ }
+
+ if (copts.misaligned_mem_access)
+ align = 4;
+
+ store_word_of_small_struct(srcReg, dstOpnd->reg, dstOpnd, dstOpnd->immOffset, type->size, align);
+}
+
+void store_small_block_from_reg_pair(short srcRegLo, short srcRegHi, Operand *dstOpnd, Type *type, SInt32 align) {
+ short tmpReg;
+
+ coerce_to_addressable(dstOpnd);
+
+ if (dstOpnd->optype == OpndType_IndirectGPR_Indexed) {
+ CError_FATAL(860);
+
+ tmpReg = used_virtual_registers[RegClass_GPR]++;
+ load_address(tmpReg, dstOpnd);
+ dstOpnd->optype = OpndType_IndirectGPR_ImmOffset;
+ dstOpnd->reg = tmpReg;
+ dstOpnd->object = NULL;
+ dstOpnd->immOffset = 0;
+ }
+
+ if (copts.misaligned_mem_access)
+ align = 4;
+
+ store_word_of_small_struct(
+ srcRegLo, dstOpnd->reg, dstOpnd,
+ dstOpnd->immOffset + low_offset, type->size - 4, align);
+ store_word_of_small_struct(
+ srcRegHi, dstOpnd->reg, dstOpnd,
+ dstOpnd->immOffset + high_offset, 4, align);
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c
new file mode 100644
index 0000000..4bbd82e
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Switch.c
@@ -0,0 +1,518 @@
+#include "compiler/Switch.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CParser.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/TOC.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+
+ObjectList *switchtables;
+static SwitchCase **caselabels;
+static CaseRange *caseranges;
+static SInt32 ncases;
+static SInt32 nranges_minus1;
+static CInt64 min;
+static CInt64 max;
+static CInt64 first;
+static short selector_gpr;
+static short selector_gprHi;
+static Type *selector_type;
+static PCodeLabel *defaultlabel;
+static CInt64 range;
+
+static int compare_cases(const void *a, const void *b) {
+ const SwitchCase **casea = (const SwitchCase **) a;
+ const SwitchCase **caseb = (const SwitchCase **) b;
+
+ if (CInt64_Less((*casea)->min, (*caseb)->min))
+ return -1;
+ if (CInt64_Greater((*casea)->min, (*caseb)->min))
+ return 1;
+ return 0;
+}
+
+static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) {
+ SwitchCase **caseptr;
+ SInt32 i;
+ SwitchCase *curcase;
+ CaseRange *currange;
+
+ if (type->size == 8) {
+ min.lo = 0;
+ min.hi = 0x80000000;
+ max.lo = 0xFFFFFFFF;
+ max.hi = 0x7FFFFFFF;
+ } else if (type->size == 4) {
+ CInt64_SetLong(&min, 0x80000000);
+ CInt64_SetLong(&max, 0x7FFFFFFF);
+ } else if (is_unsigned(type)) {
+ min.hi = 0;
+ min.lo = 0;
+ max.hi = 0;
+ max.lo = 0xFFFF;
+ } else {
+ CInt64_SetLong(&min, -0x8000);
+ CInt64_SetLong(&max, 0x7FFF);
+ }
+
+ caselabels = lalloc(sizeof(SwitchCase *) * ncases);
+ caseptr = caselabels;
+ while (cases) {
+ *caseptr = cases;
+ cases = cases->next;
+ ++caseptr;
+ }
+
+ caseranges = lalloc(((ncases * 2) + 2) * sizeof(CaseRange));
+ if (type->size < 8) {
+ for (i = 0; i < ncases; i++)
+ CInt64_SetLong(&caselabels[i]->min, caselabels[i]->min.lo);
+ }
+
+ qsort(caselabels, ncases, sizeof(SwitchCase *), &compare_cases);
+
+ currange = caseranges;
+ currange->min = min;
+ currange->range = CInt64_Sub(max, min);
+ currange->label = label->pclabel;
+
+ for (i = 0; i < ncases; i++) {
+ curcase = caselabels[i];
+ if (CInt64_GreaterEqual(curcase->min, min) && CInt64_LessEqual(curcase->min, max)) {
+ if (CInt64_Equal(currange->min, min))
+ first = curcase->min;
+ range = CInt64_Sub(curcase->min, first);
+
+ if (CInt64_Greater(curcase->min, currange->min)) {
+ currange->range = CInt64_Sub(CInt64_Sub(curcase->min, currange->min), cint64_one);
+ (++currange)->min = curcase->min;
+ } else if (CInt64_Greater(currange->min, min) && curcase->label->pclabel == currange[-1].label) {
+ currange[-1].range = CInt64_Add(currange[-1].range, cint64_one);
+ if (CInt64_Equal(currange->range, cint64_zero)) {
+ currange--;
+ } else {
+ currange->min = CInt64_Add(currange->min, cint64_one);
+ currange->range = CInt64_Sub(currange->range, cint64_one);
+ }
+ continue;
+ }
+
+ currange->range = cint64_zero;
+ currange->label = curcase->label->pclabel;
+
+ if (CInt64_Less(curcase->min, max)) {
+ currange++;
+ currange->min = CInt64_Add(curcase->min, cint64_one);
+ currange->range = CInt64_Sub(max, currange->min);
+ currange->label = label->pclabel;
+ }
+ }
+ }
+
+ nranges_minus1 = currange - caseranges;
+}
+
+static void treecompare(SInt32 start, SInt32 end) {
+ SInt32 r30;
+ SInt32 r29;
+ CaseRange *currange;
+ int count;
+
+ count = end - start;
+ CError_ASSERT(175, selector_type->size <= 4);
+
+ r29 = start + (count >> 1) + 1;
+ currange = caseranges + r29;
+
+ if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) {
+ currange--;
+ r29--;
+ }
+
+ r30 = r29 - 1;
+
+ if (selector_type->size < 4 && is_unsigned(selector_type)) {
+ emitpcode(PC_CMPLI, 0, selector_gpr, CInt64_GetULong(&currange->min));
+ } else if (FITS_IN_SHORT((SInt32) CInt64_GetULong(&currange->min))) {
+ emitpcode(PC_CMPI, 0, selector_gpr, CInt64_GetULong(&currange->min));
+ } else {
+ SInt32 value = CInt64_GetULong(&currange->min);
+ int reg = ALLOC_GPR();
+ load_immediate(reg, value);
+ emitpcode(PC_CMP, 0, selector_gpr, reg);
+ }
+
+ if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) {
+ branch_conditional(0, EEQU, 1, currange->label);
+ r29++;
+ }
+
+ if (r29 == end) {
+ if (start == r30) {
+ if (caseranges[start].label == caseranges[end].label) {
+ branch_always(caseranges[start].label);
+ } else {
+ branch_conditional(0, EGREATEREQU, 1, caseranges[end].label);
+ branch_always(caseranges[start].label);
+ }
+ } else {
+ branch_conditional(0, EGREATEREQU, 1, caseranges[end].label);
+ treecompare(start, r30);
+ }
+ } else {
+ if (start == r30) {
+ branch_conditional(0, ELESS, 1, caseranges[start].label);
+ treecompare(r29, end);
+ } else {
+ PCodeLabel *label = makepclabel();
+ branch_conditional(0, EGREATEREQU, 1, label);
+ treecompare(start, r30);
+ branch_label(label);
+ treecompare(r29, end);
+ }
+ }
+}
+
+static void I8_treecompare(SInt32 start, SInt32 end) {
+ SInt32 r30;
+ SInt32 r29;
+ CaseRange *currange;
+ int count;
+
+ count = end - start;
+
+ r29 = start + (count >> 1) + 1;
+ currange = caseranges + r29;
+
+ if (CInt64_Equal(currange[-1].range, cint64_zero) && (!(count & 1) || (CInt64_NotEqual(currange->range, cint64_zero) && count > 1))) {
+ currange--;
+ r29--;
+ }
+
+ r30 = r29 - 1;
+
+ if (CInt64_Equal(currange->range, cint64_zero) && r29 < end) {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ emitpcode(PC_XOR, a, selector_gpr, a);
+ emitpcode(PC_XOR, b, selector_gprHi, b);
+ emitpcode(PC_OR, b, a, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, currange->label);
+ r29++;
+ }
+
+ if (r29 == end) {
+ if (start == r30) {
+ if (caseranges[start].label == caseranges[end].label) {
+ branch_always(caseranges[start].label);
+ } else {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, c);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, caseranges[end].label);
+ branch_always(caseranges[start].label);
+ }
+ } else {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, c);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, EEQU, 1, caseranges[end].label);
+ I8_treecompare(start, r30);
+ }
+ } else {
+ if (start == r30) {
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, selector_gpr, a);
+ emitpcode(PC_SUBFE, b, c, d);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ branch_conditional(0, ENOTEQU, 1, caseranges[end].label);
+ I8_treecompare(r29, end);
+ } else {
+ PCodeLabel *label;
+ short a = ALLOC_GPR();
+ short b = ALLOC_GPR();
+ short c = ALLOC_GPR();
+ short d = ALLOC_GPR();
+ load_immediate(a, currange->min.lo);
+ load_immediate(b, currange->min.hi);
+ if (TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG && TYPE_INTEGRAL(selector_type)->integral != IT_ULONGLONG) {
+ emitpcode(PC_XORIS, c, selector_gprHi, 0x8000);
+ emitpcode(PC_XORIS, d, b, 0x8000);
+ } else {
+ c = selector_gprHi;
+ d = b;
+ }
+ emitpcode(PC_SUBFC, a, a, selector_gpr);
+ emitpcode(PC_SUBFE, b, d, c);
+ emitpcode(PC_SUBFE, b, a, a);
+ emitpcode(PC_NEG, b, b);
+ emitpcode(PC_CMPI, 0, b, 0);
+ label = makepclabel();
+ branch_conditional(0, EEQU, 1, label);
+ I8_treecompare(start, r30);
+ branch_label(label);
+ I8_treecompare(r29, end);
+ }
+ }
+}
+
+static void generate_tree(ENode *expr) {
+ Operand op;
+
+ memclrw(&op, sizeof(Operand));
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ GEN_NODE(expr, &op);
+ coerce_to_register_pair(&op, expr->rtype, 0, 0);
+ selector_type = expr->rtype;
+ selector_gpr = op.reg;
+ selector_gprHi = op.regHi;
+ I8_treecompare(0, nranges_minus1);
+ } else {
+ GEN_NODE(expr, &op);
+ if (expr->rtype->size < 4)
+ extend32(&op, expr->rtype, 0);
+ ENSURE_GPR(&op, expr->rtype, 0);
+ selector_type = expr->rtype;
+ selector_gpr = op.reg;
+ treecompare(0, nranges_minus1);
+ }
+}
+
+static Object *create_switch_table(void) {
+ Object *obj;
+ ObjectList *list;
+ UInt32 *outptr;
+ CaseRange *currange;
+ SInt32 size;
+ CInt64 value;
+
+ obj = galloc(sizeof(Object));
+ list = galloc(sizeof(ObjectList));
+ memclrw(obj, sizeof(Object));
+ memclrw(list, sizeof(ObjectList));
+
+ obj->otype = OT_OBJECT;
+ obj->access = ACCESSPUBLIC;
+ obj->datatype = DDATA;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->sclass = TK_STATIC;
+ obj->qual = Q_CONST;
+ obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED;
+ obj->u.data.linkname = obj->name;
+ obj->type = NULL;
+ createIndirect(obj, 0, 0);
+ obj->type = TYPE(&void_ptr);
+
+ size = CInt64_GetULong(&range) + 1;
+ obj->u.data.u.switchtable.size = size;
+ obj->u.data.u.switchtable.data = lalloc(4 * size);
+
+ currange = caseranges;
+ outptr = (UInt32 *) obj->u.data.u.switchtable.data;
+ value = cint64_zero;
+ while (CInt64_LessEqual(value, range)) {
+ while (CInt64_Greater(CInt64_Add(first, value), CInt64_Add(currange->min, currange->range)))
+ currange++;
+ *outptr = CTool_CreateIndexFromPointer(currange->label);
+ value = CInt64_Add(value, cint64_one);
+ outptr++;
+ }
+
+ list->object = obj;
+ list->next = switchtables;
+ switchtables = list;
+ return list->object;
+}
+
+static void generate_table(ENode *expr, SwitchInfo *info) {
+ Object *table;
+ SwitchCase *curcase;
+ short reg;
+ short reg2;
+ short reg3;
+ Operand op1;
+ Operand op2;
+
+ CInt64 val3 = {0, 3};
+ memclrw(&op1, sizeof(Operand));
+ memclrw(&op2, sizeof(Operand));
+
+ if (CInt64_Greater(first, cint64_zero) && CInt64_Less(first, val3)) {
+ range = CInt64_Add(range, first);
+ first = cint64_zero;
+ }
+
+ table = create_switch_table();
+ CError_ASSERT(553, !TYPE_IS_8BYTES(expr->rtype));
+
+ GEN_NODE(expr, &op1);
+ if (expr->rtype->size < 4)
+ extend32(&op1, expr->rtype, 0);
+ ENSURE_GPR(&op1, expr->rtype, 0);
+
+ reg = op1.reg;
+ if (CInt64_NotEqual(first, cint64_zero)) {
+ SInt32 value;
+ reg = ALLOC_GPR();
+ value = -CInt64_GetULong(&first);
+ if (!FITS_IN_SHORT(value)) {
+ emitpcode(PC_ADDIS, reg, op1.reg, 0, HIGH_PART(value));
+ if (value)
+ emitpcode(PC_ADDI, reg, reg, 0, LOW_PART(value));
+ } else {
+ emitpcode(PC_ADDI, reg, op1.reg, 0, value);
+ }
+ }
+
+ if (!FITS_IN_SHORT(CInt64_GetULong(&range))) {
+ short tmp = ALLOC_GPR();
+ load_immediate(tmp, CInt64_GetULong(&range));
+ emitpcode(PC_CMPL, 0, reg, tmp);
+ } else {
+ emitpcode(PC_CMPLI, 0, reg, CInt64_GetULong(&range));
+ }
+
+ branch_conditional(0, EGREATER, 1, defaultlabel);
+ if (table->toc) {
+ op2.optype = OpndType_Symbol;
+ op2.object = table->toc;
+ indirect(&op2, NULL);
+ } else {
+ op2.optype = OpndType_Symbol;
+ op2.object = table;
+ }
+
+ if (op2.optype != OpndType_GPR) {
+ Coerce_to_register(&op2, TYPE(&void_ptr), reg2 = ALLOC_GPR());
+ }
+
+ if (op2.optype != OpndType_GPR) {
+ CError_FATAL(599);
+ } else {
+ if (op2.reg != reg2)
+ emitpcode(PC_MR, reg2, op2.reg);
+ }
+
+ if (CInt64_Equal(first, cint64_zero)) {
+ reg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, op1.reg, 2, 0, 29);
+ } else {
+ emitpcode(PC_RLWINM, reg, reg, 2, 0, 29);
+ }
+
+ reg3 = reg2;
+ emitpcode(PC_LWZX, reg3, reg3, reg);
+ for (curcase = info->cases; curcase; curcase = curcase->next)
+ pcbranch(pclastblock, curcase->label->pclabel);
+ pcbranch(pclastblock, info->defaultlabel->pclabel);
+ emitpcode(PC_MTCTR, reg3);
+ branch_indirect(table);
+}
+
+void switchstatement(ENode *expr, SwitchInfo *info) {
+ Boolean use_table;
+ SwitchCase *swcase;
+
+ use_table = copts.switch_tables;
+
+ ncases = 0;
+ for (swcase = info->cases; swcase; swcase = swcase->next) {
+ if (!swcase->label->pclabel)
+ swcase->label->pclabel = makepclabel();
+ ncases++;
+ }
+
+ CError_ASSERT(656, ncases >= 0 && ncases <= 0x3333332U);
+
+ if (!info->defaultlabel->pclabel)
+ info->defaultlabel->pclabel = makepclabel();
+ defaultlabel = info->defaultlabel->pclabel;
+
+ build_case_ranges(expr->rtype, info->cases, info->defaultlabel);
+
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ generate_tree(expr);
+ return;
+ }
+
+ if (!use_table || nranges_minus1 < 8 || (nranges_minus1 * 2) < ((range.lo / 2) + 4))
+ generate_tree(expr);
+ else
+ generate_table(expr, info);
+}
+
+void dumpswitchtables(Object *funcobj) {
+ Object *table;
+ ObjectList *list;
+ SInt32 size;
+ UInt32 *array;
+
+ for (list = switchtables; list; list = list->next) {
+ table = list->object;
+ CError_ASSERT(694, table->otype == OT_OBJECT && table->access == ACCESSPUBLIC && table->datatype == DDATA);
+
+ size = table->u.data.u.switchtable.size;
+ array = (UInt32 *) table->u.data.u.switchtable.data;
+ while (size--) {
+ *array = CTool_EndianConvertWord32(((PCodeLabel *) CTool_ResolveIndexToPointer(*array))->block->codeOffset);
+ array++;
+ }
+
+ ObjGen_DeclareSwitchTable(table, funcobj);
+ }
+}
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c
new file mode 100644
index 0000000..7af09e3
--- /dev/null
+++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/TOC.c
@@ -0,0 +1,2272 @@
+#include "cos.h"
+#include "compiler/TOC.h"
+#include "compiler/CDecl.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CInit.h"
+#include "compiler/CInt64.h"
+#include "compiler/CFunc.h"
+#include "compiler/CMachine.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/Exceptions.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/Intrinsics.h"
+#include "compiler/ObjGenMachO.h"
+#include "compiler/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PPCError.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+ObjectList *toclist;
+ObjectList *exceptionlist;
+void *descriptorlist;
+PoolEntry *floatconstpool;
+PoolEntry *doubleconstpool;
+ObjectList *floatconstlist;
+PoolEntry *vectorconstpool;
+ObjectList *vectorconstlist;
+Object toc0;
+Boolean no_descriptors;
+Object pic_base;
+VarInfo pic_base_varinfo;
+short pic_base_reg;
+CodeLabelList *codelabellist;
+
+UInt8 lvslBytes[16][16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E
+};
+
+UInt8 lvsrBytes[16][16] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+ 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
+ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
+};
+
+// forward decls
+static void estimate_func_param_size(ENode *node);
+
+static int disables_optimizer(ENode *node) {
+ ENode *funcref = node->data.funccall.funcref;
+ if (ENODE_IS(funcref, EOBJREF)) {
+ if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___setjmp"))
+ return 1;
+ if (!strcmp(CMangler_GetLinkName(funcref->data.objref)->name, "___vec_setjmp"))
+ return 1;
+ }
+ return 0;
+}
+
+void setupaddressing(void) {
+ floatconstlist = NULL;
+ descriptorlist = NULL;
+ toclist = NULL;
+ exceptionlist = NULL;
+ vectorconstlist = NULL;
+ vectorconstpool = NULL;
+ floatconstpool = NULL;
+ doubleconstpool = NULL;
+
+ no_descriptors = 1;
+ memclrw(&toc0, sizeof(toc0));
+
+ pic_base_reg = 0;
+ memclrw(&pic_base, sizeof(pic_base));
+ memclrw(&pic_base_varinfo, sizeof(pic_base_varinfo));
+ pic_base.otype = OT_OBJECT;
+ pic_base.type = (Type *) &void_ptr;
+ pic_base.datatype = DNONLAZYPTR;
+ pic_base.u.toc.info = &pic_base_varinfo;
+}
+
+void createNonLazyPointer(Object *obj) {
+ Object *toc;
+ ObjectList *list;
+
+ toc = galloc(sizeof(Object));
+ obj->toc = toc;
+ memclrw(toc, sizeof(Object));
+
+ toc->otype = OT_OBJECT;
+ toc->name = CParser_GetUniqueName();
+ toc->toc = NULL;
+ toc->section = SECT_NONLAZY_PTRS;
+ toc->u.toc.info = CodeGen_GetNewVarInfo();
+ toc->sclass = TK_STATIC;
+ toc->qual = Q_CONST;
+ toc->datatype = DNONLAZYPTR;
+ toc->flags |= OBJECT_FLAGS_2;
+ toc->type = CDecl_NewPointerType(obj->type);
+ toc->u.toc.over_load = obj;
+ toc->u.toc.linkname = CMangler_GetLinkName(obj);
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = toc;
+ list->next = toclist;
+ toclist = list;
+}
+
+void referenceIndirectPointer(Object *obj) {
+ VarInfo *vi = obj->toc->u.toc.info;
+ vi->used = 1;
+ vi->usage += copts.optimizesize ? 1 : curstmtvalue;
+}
+
+Object *createIndirect(Object *obj, Boolean flag1, Boolean flag2) {
+ CError_ASSERT(622, !copts.no_common || (obj->section != SECT_COMMON_VARS) || (obj->qual & Q_20000));
+
+ if (CParser_HasInternalLinkage(obj))
+ return NULL;
+ if (ObjGen_IsExported(obj))
+ return NULL;
+
+ if (!copts.no_common && obj->datatype == DDATA && obj->section == SECT_DEFAULT && (obj->qual & Q_1000000))
+ obj->section = SECT_COMMON_VARS;
+
+ if (copts.codegen_dynamic && (!copts.no_common || !(obj->qual & Q_1000000))) {
+ if (!obj->toc)
+ createNonLazyPointer(obj);
+ else if (flag1)
+ obj->toc->u.toc.info = CodeGen_GetNewVarInfo();
+
+ if (flag2)
+ referenceIndirectPointer(obj);
+
+ return obj->toc;
+ } else {
+ return NULL;
+ }
+}
+
+Object *createfloatconstant(Type *type, Float *data) {
+ ObjectList *list;
+ Object *obj;
+ UInt32 *check;
+
+ for (list = floatconstlist; list; list = list->next) {
+ obj = list->object;
+ check = (UInt32 *) obj->u.data.u.floatconst;
+ if (obj->type == type && check[0] == ((UInt32 *) data)[0] && check[1] == ((UInt32 *) data)[1])
+ return obj;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->u.data.info = NULL;
+ obj->u.data.linkname = obj->name;
+ obj->sclass = TK_STATIC;
+ obj->qual = Q_CONST | Q_INLINE_DATA;
+ obj->datatype = DDATA;
+ if (type->size == 8)
+ obj->section = SECT_8BYTE_LITERALS;
+ else if (type->size == 4)
+ obj->section = SECT_4BYTE_LITERALS;
+ else
+ CError_FATAL(807);
+
+ obj->flags |= OBJECT_FLAGS_2;
+
+ obj->u.data.u.floatconst = galloc(sizeof(Float));
+ *obj->u.data.u.floatconst = *data;
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = floatconstlist;
+ floatconstlist = list;
+
+ ObjGen_DeclareFloatConst(obj);
+ return obj;
+}
+
+Object *createvectorconstant(Type *type, MWVector128 *data) {
+ ObjectList *list;
+ Object *obj;
+ MWVector128 *check;
+
+ for (list = vectorconstlist; list; list = list->next) {
+ obj = list->object;
+ check = obj->u.data.u.vector128const;
+ if (check->ul[0] == data->ul[0] && check->ul[1] == data->ul[1] && check->ul[2] == data->ul[2] && check->ul[3] == data->ul[3])
+ return obj;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = type;
+ obj->name = CParser_GetUniqueName();
+ obj->toc = NULL;
+ obj->u.data.info = NULL;
+ obj->u.data.linkname = obj->name;
+ obj->sclass = TK_STATIC;
+ obj->qual = Q_CONST | Q_INLINE_DATA;
+ obj->datatype = DDATA;
+ if (type->size == 16)
+ obj->section = SECT_16BYTE_LITERALS;
+ else
+ CError_FATAL(900);
+
+ obj->flags |= OBJECT_FLAGS_2;
+
+ obj->u.data.u.vector128const = galloc(sizeof(MWVector128));
+ *obj->u.data.u.vector128const = *data;
+
+ list = galloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = vectorconstlist;
+ vectorconstlist = list;
+
+ ObjGen_DeclareVectorConst(obj);
+ return obj;
+}
+
+void DeclarePooledConstants(void) {
+ PoolEntry *entry;
+ char *buffer;
+ SInt32 fsize;
+ SInt32 dsize;
+ SInt32 vsize;
+
+ fsize = 0;
+ for (entry = floatconstpool; entry; entry = entry->next)
+ fsize += 4;
+
+ if (fsize) {
+ floatconstpool->object->type = CDecl_NewArrayType(TYPE(&stfloat), fsize);
+ buffer = galloc(fsize);
+ for (entry = floatconstpool; entry; entry = entry->next)
+ memcpy(buffer + entry->offset, entry->buffer, 4);
+ CInit_DeclareReadOnlyData(floatconstpool->object, buffer, NULL, fsize);
+ }
+
+ dsize = 0;
+ for (entry = doubleconstpool; entry; entry = entry->next)
+ dsize += 8;
+
+ if (dsize) {
+ doubleconstpool->object->type = CDecl_NewArrayType(TYPE(&stdouble), dsize);
+ buffer = galloc(dsize);
+ for (entry = doubleconstpool; entry; entry = entry->next)
+ memcpy(buffer + entry->offset, entry->buffer, 8);
+ CInit_DeclareReadOnlyData(doubleconstpool->object, buffer, NULL, dsize);
+ }
+
+ vsize = 0;
+ for (entry = vectorconstpool; entry; entry = entry->next)
+ vsize += 16;
+
+ if (vsize) {
+ vectorconstpool->object->type = CDecl_NewArrayType(TYPE(&stvectorsignedlong), vsize);
+ buffer = galloc(vsize);
+ for (entry = vectorconstpool; entry; entry = entry->next)
+ memcpy(buffer + entry->offset, entry->buffer, 16);
+ CInit_DeclareReadOnlyData(vectorconstpool->object, buffer, NULL, vsize);
+ }
+}
+
+static Object *CreatePooledFloatConst(Type *type, Float *data, SInt32 *pOffset) {
+ if (type->size == 8u) {
+ PoolEntry *entry;
+ void *buffer;
+ Object *object;
+ SInt32 offset;
+
+ buffer = galloc(8u);
+ CMach_InitFloatMem(type, *data, buffer);
+ if (cparamblkptr->precompile == 1)
+ CError_Error(CErrorStr180);
+
+ for (entry = doubleconstpool; entry; entry = entry->next) {
+ if (!memcmp(entry->buffer, buffer, 8u))
+ break;
+ }
+
+ if (!entry) {
+ if (doubleconstpool) {
+ object = doubleconstpool->object;
+ offset = doubleconstpool->offset + 8u;
+ doubleconstpool->object->type->size += 8u;
+ } else {
+ DeclInfo di;
+ memclrw(&di, sizeof(di));
+ di.thetype = CDecl_NewArrayType(TYPE(&stdouble), 8u);
+ di.name = GetHashNameNodeExport("@doubleBase0");
+ di.qual = Q_CONST;
+ di.storageclass = TK_STATIC;
+ di.is_extern_c = 1;
+ di.section = SECT_CONST;
+ object = CParser_NewGlobalDataObject(&di);
+ object->nspace = cscope_root;
+ offset = 0;
+ }
+
+ entry = galloc(sizeof(PoolEntry));
+ entry->next = doubleconstpool;
+ doubleconstpool = entry;
+ entry->object = object;
+ entry->offset = offset;
+ entry->buffer = galloc(8u);
+ memcpy(entry->buffer, buffer, 8u);
+ }
+
+ *pOffset = entry->offset;
+ return entry->object;
+ }
+
+ if (type->size == 4u) {
+ PoolEntry *entry;
+ void *buffer;
+ Object *object;
+ SInt32 offset;
+
+ buffer = galloc(4u);
+ CMach_InitFloatMem(type, *data, buffer);
+ if (cparamblkptr->precompile == 1)
+ CError_Error(CErrorStr180);
+
+ for (entry = floatconstpool; entry; entry = entry->next) {
+ if (!memcmp(entry->buffer, buffer, 4u))
+ break;
+ }
+
+ if (!entry) {
+ if (floatconstpool) {
+ object = floatconstpool->object;
+ offset = floatconstpool->offset + 4u;
+ object->type->size += 4u;
+ } else {
+ DeclInfo di;
+ memclrw(&di, sizeof(di));
+ di.thetype = CDecl_NewArrayType(TYPE(&stfloat), 4u);
+ di.name = GetHashNameNodeExport("@floatBase0");
+ di.qual = Q_CONST;
+ di.storageclass = TK_STATIC;
+ di.is_extern_c = 1;
+ di.section = SECT_CONST;
+ object = CParser_NewGlobalDataObject(&di);
+ object->nspace = cscope_root;
+ offset = 0;
+ }
+
+ entry = galloc(sizeof(PoolEntry));
+ entry->next = floatconstpool;
+ floatconstpool = entry;
+ entry->object = object;
+ entry->offset = offset;
+ entry->buffer = galloc(4u);
+ memcpy(entry->buffer, buffer, 4u);
+ }
+
+ *pOffset = entry->offset;
+ return entry->object;
+ }
+
+ CError_FATAL(1183);
+ return NULL;
+}
+
+Object *CreateFloatConst(Type *type, Float *data, SInt32 *pOffset) {
+ *pOffset = 0;
+ return createfloatconstant(type, data);
+}
+
+static void RewriteFloatConst(ENode *expr) {
+ Object *obj;
+ SInt32 n;
+ ENode *subexpr;
+
+ obj = CreateFloatConst(expr->rtype, &expr->data.floatval, &n);
+ if (n) {
+ subexpr = makediadicnode(create_objectrefnode(obj), intconstnode(TYPE(&stunsignedlong), n), EADD);
+ } else {
+ subexpr = create_objectrefnode(obj);
+ }
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->flags |= Q_CONST;
+ expr->data.monadic = subexpr;
+}
+
+static void RewriteVectorConst(ENode *expr) {
+ PoolEntry *entry;
+ Object *object;
+ SInt32 offset;
+ ENode *inner;
+ UInt8 data[16];
+
+ CMach_InitVectorMem(expr->rtype, expr->data.vector128val, data, 1);
+
+ if (cparamblkptr->precompile == 1)
+ CError_Error(CErrorStr180);
+
+ for (entry = vectorconstpool; entry; entry = entry->next) {
+ if (!memcmp(entry->buffer, data, 16))
+ break;
+ }
+
+ if (!entry) {
+ if (vectorconstpool) {
+ object = vectorconstpool->object;
+ offset = vectorconstpool->offset + 16;
+ vectorconstpool->object->type->size += 16;
+ } else {
+ DeclInfo di;
+ memclrw(&di, sizeof(di));
+ di.thetype = CDecl_NewArrayType(TYPE(&stvectorsignedlong), 16);
+ di.name = GetHashNameNodeExport("@vectorBase0");
+ di.qual = Q_CONST;
+ di.storageclass = TK_STATIC;
+ di.is_extern_c = 1;
+ di.section = SECT_CONST;
+ object = CParser_NewGlobalDataObject(&di);
+ object->nspace = cscope_root;
+ offset = 0;
+ }
+
+ entry = galloc(sizeof(PoolEntry));
+ entry->next = vectorconstpool;
+ vectorconstpool = entry;
+ entry->object = object;
+ entry->offset = offset;
+ entry->buffer = galloc(16);
+ memcpy(entry->buffer, data, 16);
+ }
+
+ if (entry->offset) {
+ inner = makediadicnode(
+ create_objectrefnode(entry->object),
+ intconstnode(TYPE(&stunsignedlong), entry->offset),
+ EADD);
+ } else {
+ inner = create_objectrefnode(entry->object);
+ }
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->flags |= ENODE_FLAG_CONST;
+ expr->data.monadic = inner;
+}
+
+static Object *createcodelabel(CLabel *label) {
+ CodeLabelList *list;
+ Object *obj;
+
+ for (list = codelabellist; list; list = list->next) {
+ if (list->label == label)
+ return list->object;
+ }
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = (Type *) &void_ptr;
+ obj->name = label->uniquename;
+ obj->toc = NULL;
+ obj->u.data.info = NULL; // not sure if this is the right union!
+ obj->sclass = TK_STATIC;
+ obj->qual = Q_CONST;
+ obj->datatype = DDATA;
+ obj->flags |= OBJECT_FLAGS_2 | OBJECT_DEFINED;
+
+ list = galloc(sizeof(CodeLabelList));
+ memclrw(list, sizeof(CodeLabelList));
+ list->object = obj;
+ list->label = label;
+ list->next = codelabellist;
+ codelabellist = list;
+
+ return obj;
+}
+
+void dumpcodelabels(Object *func) {
+ CodeLabelList *list;
+
+ for (list = codelabellist; list; list = list->next)
+ ObjGen_DeclareCodeLabel(list->object, list->label->pclabel->block->codeOffset, func);
+}
+
+static void referenceexception(Object *obj) {
+ ObjectList *list;
+
+ if (obj && obj->otype == OT_OBJECT && obj->datatype == DLOCAL) {
+ for (list = exceptionlist; list; list = list->next) {
+ if (list->object == obj)
+ return;
+ }
+
+ list = lalloc(sizeof(ObjectList));
+ memclrw(list, sizeof(ObjectList));
+ list->object = obj;
+ list->next = exceptionlist;
+ exceptionlist = list;
+ }
+}
+
+static ENodeType invert_relop(ENodeType nodetype) {
+ switch (nodetype) {
+ case ELESS: return EGREATEREQU;
+ case EGREATER: return ELESSEQU;
+ case ELESSEQU: return EGREATER;
+ case EGREATEREQU: return ELESS;
+ case EEQU: return ENOTEQU;
+ case ENOTEQU: return EEQU;
+ default: return nodetype;
+ }
+}
+
+static ENode *COND_to_COMPARE(ENode *cond, ENode *expr1, ENode *expr2) {
+ SInt32 val1;
+ SInt32 val2;
+ SInt32 condval;
+ ENodeType invop;
+
+ while (expr1->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr1->rtype))
+ expr1 = expr1->data.monadic;
+ while (expr2->type == ETYPCON && TYPE_FITS_IN_REGISTER(expr2->rtype))
+ expr2 = expr2->data.monadic;
+
+ if (expr1->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr1->rtype) || !CInt64_IsInRange(expr1->data.intval, 4))
+ return NULL;
+ if (expr2->type != EINTCONST || !TYPE_FITS_IN_REGISTER(expr2->rtype) || !CInt64_IsInRange(expr2->data.intval, 4))
+ return NULL;
+
+ val1 = expr1->data.intval.lo;
+ val2 = expr2->data.intval.lo;
+ condval = 0;
+ switch (val1) {
+ case 1:
+ if (val2 != 0)
+ return NULL;
+ break;
+ case 0:
+ condval = 1;
+ if (val2 != 1)
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
+
+ while (cond->type == ELOGNOT) {
+ condval = (condval + 1) & 1;
+ cond = cond->data.monadic;
+ }
+
+ if (condval) {
+ invop = invert_relop(cond->type);
+ if (invop == cond->type)
+ return NULL;
+ cond->type = invop;
+ }
+
+ return cond;
+}
+
+static ENode *comparewithzero(ENode *expr) {
+ ENode *expr1;
+ ENode *expr2;
+ ENode *tmp;
+
+ expr1 = lalloc(sizeof(ENode));
+ memclrw(expr1, sizeof(ENode));
+ expr2 = lalloc(sizeof(ENode));
+ memclrw(expr2, sizeof(ENode));
+
+ while (expr->type == EFORCELOAD || expr->type == ETYPCON || expr->type == ECOMMA) {
+ if (!TYPE_FITS_IN_REGISTER(expr->rtype))
+ break;
+ if (expr->type == ECOMMA) {
+ expr->data.diadic.right = comparewithzero(expr->data.diadic.right);
+ return expr;
+ }
+ expr = expr->data.monadic;
+ }
+
+ if (expr->type == ECOND && TYPE_FITS_IN_REGISTER(expr->rtype)) {
+ tmp = COND_to_COMPARE(expr->data.cond.cond, expr->data.cond.expr1, expr->data.cond.expr2);
+ if (tmp)
+ expr = tmp;
+ }
+
+ if (expr->type >= ELESS && expr->type <= ENOTEQU)
+ return expr;
+
+ if (IS_TYPE_FLOAT(expr->rtype)) {
+ static Float float0 = {0.0};
+
+ expr2->type = EFLOATCONST;
+ expr2->cost = 0;
+ expr2->rtype = (expr->rtype->size == 4) ? (Type *) &stfloat : (Type *) &stdouble;
+ expr2->data.floatval = float0;
+ } else {
+ expr2->type = EINTCONST;
+ expr2->cost = 0;
+ if (TYPE_IS_8BYTES(expr->rtype))
+ expr2->rtype = (Type *) &stsignedlonglong;
+ else
+ expr2->rtype = (Type *) &stsignedint;
+ expr2->data.intval.lo = 0;
+ expr2->data.intval.hi = 0;
+ }
+
+ expr1->type = ENOTEQU;
+ expr1->cost = expr->cost;
+ expr1->rtype = (Type *) &stsignedint;
+ expr1->data.diadic.left = expr;
+ expr1->data.diadic.right = expr2;
+ return expr1;
+}
+
+static void rewritefunctioncallreturningstruct(ENode *expr) {
+ ENode *ret_expr;
+ ENode *copy;
+
+ ret_expr = expr->data.funccall.args->node;
+
+ copy = lalloc(sizeof(ENode));
+ memclrw(copy, sizeof(ENode));
+
+ *copy = *expr;
+ expr->type = ECOMMA;
+ expr->data.diadic.left = copy;
+ expr->data.diadic.right = ret_expr;
+}
+
+static void rewritestrcpy(ENode *expr) {
+ ENode *int_expr;
+ ENodeList *list;
+
+ int_expr = lalloc(sizeof(ENode));
+ memclrw(int_expr, sizeof(ENode));
+ int_expr->type = EINTCONST;
+ int_expr->cost = 0;
+ int_expr->flags = 0;
+ int_expr->rtype = (Type *) &stunsignedlong;
+ CInt64_SetLong(&int_expr->data.intval, expr->data.funccall.args->next->node->data.string.size);
+
+ list = lalloc(sizeof(ENodeList));
+ memclrw(list, sizeof(ENodeList));
+ list->next = NULL;
+ list->node = int_expr;
+ expr->data.funccall.args->next->next = list;
+ expr->data.funccall.funcref->data.objref = __memcpy_object;
+}
+
+static SInt32 magnitude(Type *type) {
+ if (IS_TYPE_FLOAT(type))
+ return type->size * 4;
+ else if (is_unsigned(type))
+ return (type->size * 2) + 1;
+ else
+ return type->size * 2;
+}
+
+static Type *promote_type(Type *type) {
+ if (IS_TYPE_ENUM(type))
+ type = TYPE_ENUM(type)->enumtype;
+ if (TYPE_INTEGRAL(type)->integral > stsignedint.integral)
+ return type;
+ else
+ return (Type *) &stsignedint;
+}
+
+static Type *common_type(Type *type1, Type *type2) {
+ Type *tmp;
+
+ if (IS_TYPE_FLOAT(type1) || IS_TYPE_FLOAT(type2)) {
+ if (TYPE_INTEGRAL(type1)->integral > TYPE_INTEGRAL(type2)->integral)
+ return type1;
+ else
+ return type2;
+ }
+
+ type1 = promote_type(type1);
+ type2 = promote_type(type2);
+ if (type1 != type2) {
+ if (TYPE_INTEGRAL(type1)->integral < TYPE_INTEGRAL(type2)->integral) {
+ tmp = type1;
+ type1 = type2;
+ type2 = tmp;
+ }
+
+ if (type1->size == type2->size && !is_unsigned(type1) && is_unsigned(type2)) {
+ if (type1 == (Type *) &stsignedlong) {
+ type1 = (Type *) &stunsignedlong;
+ } else {
+ CError_ASSERT(1789, type1 == (Type *) &stsignedlonglong);
+ type1 = (Type *) &stunsignedlonglong;
+ }
+ }
+ }
+
+ return type1;
+}
+
+static void rewrite_opassign(ENode *expr, ENodeType exprtype) {
+ ENode *left_sub;
+ ENode *right;
+ Type *left_type;
+ Type *right_type;
+ ENode *new_expr;
+ ENode *tmp;
+ Type *commontype;
+ Type *promo_left;
+ Type *promo_right;
+
+ left_sub = expr->data.diadic.left->data.monadic;
+ right = expr->data.diadic.right;
+ left_type = expr->data.diadic.left->rtype;
+ right_type = expr->data.diadic.right->rtype;
+
+ new_expr = lalloc(sizeof(ENode));
+ memclrw(new_expr, sizeof(ENode));
+ new_expr->type = exprtype;
+ new_expr->rtype = left_type;
+ new_expr->data.diadic.left = expr->data.diadic.left;
+ new_expr->data.diadic.right = right;
+
+ expr->type = EASS;
+ expr->data.diadic.left = left_sub;
+ expr->data.diadic.right = new_expr;
+
+ if (left_sub->type != EOBJREF) {
+ ENode *define;
+ ENode *reuse;
+
+ define = lalloc(sizeof(ENode));
+ memclrw(define, sizeof(ENode));
+ define->type = EDEFINE;
+ define->rtype = left_type;
+
+ reuse = lalloc(sizeof(ENode));
+ memclrw(reuse, sizeof(ENode));
+ reuse->type = EREUSE;
+ reuse->rtype = left_type;
+ reuse->data.monadic = define;
+
+ if (left_sub->type != EBITFIELD) {
+ define->data.monadic = expr->data.diadic.left;
+ expr->data.diadic.left = define;
+ new_expr->data.diadic.left->data.diadic.left = reuse;
+ } else {
+ ENode *copy;
+ define->data.monadic = left_sub->data.diadic.left;
+ left_sub->data.diadic.left = define;
+
+ copy = lalloc(sizeof(ENode));
+ *copy = *left_sub;
+ copy->data.diadic.left = reuse;
+ new_expr->data.diadic.left->data.diadic.left = copy;
+ }
+ }
+
+ switch (exprtype) {
+ case EADD:
+ case ESUB:
+ if (IS_TYPE_POINTER(left_type))
+ break;
+ if (right->type == EINTCONST && TYPE_FITS_IN_REGISTER(left_type))
+ break;
+ case EAND:
+ case EXOR:
+ case EOR:
+ if (left_type == right_type)
+ break;
+ case EMUL:
+ case EDIV:
+ case EMODULO:
+ commontype = common_type(left_type, right_type);
+ if (left_type != commontype) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = left_type;
+ tmp->data.monadic = expr->data.diadic.right;
+ expr->data.diadic.right = tmp;
+
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = commontype;
+ tmp->data.monadic = new_expr->data.diadic.left;
+ new_expr->data.diadic.left = tmp;
+ }
+ if (right_type != commontype) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = commontype;
+ tmp->data.monadic = new_expr->data.diadic.right;
+ new_expr->data.diadic.right = tmp;
+ }
+ new_expr->rtype = commontype;
+ break;
+
+ case ESHL:
+ case ESHR:
+ promo_left = promote_type(left_type);
+ promo_right = promote_type(right_type);
+ if (left_type != promo_left) {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = left_type;
+ tmp->data.monadic = expr->data.diadic.right;
+ expr->data.diadic.right = tmp;
+
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = promo_left;
+ tmp->data.monadic = new_expr->data.diadic.left;
+ new_expr->data.diadic.left = tmp;
+ }
+ if (right_type != promo_right) {
+ if (new_expr->data.diadic.right->type == EINTCONST && promo_right == (Type *) &stsignedint) {
+ new_expr->data.diadic.right->rtype = (Type *) &stsignedint;
+ } else {
+ tmp = lalloc(sizeof(ENode));
+ memclrw(tmp, sizeof(ENode));
+ tmp->type = ETYPCON;
+ tmp->rtype = promo_right;
+ tmp->data.monadic = new_expr->data.diadic.right;
+ new_expr->data.diadic.right = tmp;
+ }
+ }
+ new_expr->rtype = promo_left;
+ break;
+ }
+}
+
+static void rewrite_preincdec(ENode *expr) {
+ ENode *subexpr; // r31
+ Type *type; // r28
+ ENode *new_expr; // r29
+
+ subexpr = expr->data.monadic;
+ type = expr->rtype;
+
+ new_expr = lalloc(sizeof(ENode));
+ memclrw(new_expr, sizeof(ENode));
+
+ if (IS_TYPE_FLOAT(type)) {
+ new_expr->type = EFLOATCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = type;
+ new_expr->data.floatval = one_point_zero;
+ } else if (IS_TYPE_POINTER(type)) {
+ new_expr->type = EINTCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = (Type *) &stunsignedlong;
+ new_expr->data.intval.hi = 0;
+ new_expr->data.intval.lo = TYPE_POINTER(type)->target->size;
+ } else {
+ new_expr->type = EINTCONST;
+ new_expr->cost = 0;
+ new_expr->rtype = type;
+ new_expr->data.intval.hi = 0;
+ new_expr->data.intval.lo = 1;
+ }
+
+ expr->type = (expr->type == EPREDEC) ? ESUBASS : EADDASS;
+ expr->data.diadic.left = subexpr;
+ expr->data.diadic.right = new_expr;
+}
+
+// Don't know what this would be called in the original, but weh
+typedef union signed_vec {
+ SInt8 sc[16];
+ SInt16 ss[8];
+ SInt32 sl[4];
+} signed_vec;
+
+Boolean canoptimizevectorconst(MWVector128 *vecp, Type *type, COVCResult *result) {
+ // this function is very broken
+ signed_vec vec;
+ union { SInt32 lg; SInt8 ch[4]; } conv32;
+ union { SInt16 sh; SInt8 ch[2]; } conv16;
+ char flag;
+ SInt8 first8;
+ SInt16 first16;
+ SInt32 first32;
+ int i;
+ char ci;
+ UInt32 l0, l1, l2, l3;
+
+ if (IS_TYPE_VECTOR(type)) {
+ vec = *((signed_vec *) vecp);
+
+ first8 = vec.sc[0];
+ flag = 1;
+ i = 1;
+ while (flag && i < 16)
+ flag = first8 == vec.sc[i++];
+ /*flag = 1;
+ for (i = 1; flag && i < 16; i++) {
+ flag = first8 == vec.sc[i];
+ }*/
+
+ if (flag && first8 < 16 && first8 > -17) {
+ if (result) {
+ result->op1 = PC_VSPLTISB;
+ result->op2 = -1;
+ result->arg = first8;
+ }
+ return 1;
+ }
+
+ first16 = vec.ss[0];
+ flag = 1;
+ for (i = 1; flag && i < 8; i++) {
+ flag = vec.ss[i] == first16;
+ }
+
+ conv16.sh = first16;
+ if (flag && conv16.ch[0] == 0 && conv16.ch[1] < 16 && conv16.ch[1] >= 0) {
+ if (result) {
+ result->op1 = PC_VSPLTISH;
+ result->op2 = -1;
+ result->arg = conv16.ch[1];
+ }
+ return 1;
+ }
+
+ if (flag && conv16.ch[0] == -1 && (conv16.ch[1] & 0xF0) == 0xF0) {
+ if (result) {
+ result->op1 = PC_VSPLTISH;
+ result->op2 = -1;
+ result->arg = conv16.ch[1];
+ }
+ return 1;
+ }
+
+ first32 = vec.sl[0];
+ flag = 1;
+ for (i = 1; flag && i < 4; i++) {
+ flag = vec.sl[i] == first32;
+ }
+
+ conv32.lg = first32;
+ if (flag && conv32.ch[0] == 0 && conv32.ch[1] == 0 && conv32.ch[2] == 0 && conv32.ch[3] < 16 && conv32.ch[3] >= 0) {
+ if (result) {
+ result->op1 = PC_VSPLTISW;
+ result->op2 = -1;
+ result->arg = conv32.ch[3];
+ }
+ return 1;
+ }
+
+ if (flag && conv32.ch[0] == -1 && conv32.ch[1] == -1 && conv32.ch[2] == -1 && (conv32.ch[3] & 0xF0) == 0xF0) {
+ if (result) {
+ result->op1 = PC_VSPLTISW;
+ result->op2 = -1;
+ result->arg = conv32.ch[3];
+ }
+ return 1;
+ }
+
+ l0 = vec.sl[0];
+ l1 = vec.sl[1];
+ l2 = vec.sl[2];
+ l3 = vec.sl[3];
+ for (ci = 0; ci < 16; ci++) {
+ UInt32 *l;
+ UInt32 *r;
+
+ l = (UInt32 *) lvslBytes[(char) ci];
+ r = (UInt32 *) lvsrBytes[(char) ci];
+ if (l0 == l[0] && l1 == l[1] && l2 == l[2] && l3 == l[3]) {
+ if (result) {
+ result->op1 = -1;
+ result->op2 = PC_LVSL;
+ result->arg = ci;
+ }
+ return 1;
+ }
+ if (l0 == r[0] && l1 == r[1] && l2 == r[2] && l3 == r[3]) {
+ if (result) {
+ result->op1 = -1;
+ result->op2 = PC_LVSR;
+ result->arg = ci;
+ }
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static SInt32 countindirects(ENode *expr) {
+ SInt32 tmp1;
+ SInt32 tmp2;
+
+ switch (expr->type) {
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ return 0;
+ case ECOND:
+ if (expr->data.cond.cond->hascall || expr->data.cond.expr1->hascall || expr->data.cond.expr2->hascall)
+ return 2;
+
+ if ((tmp1 = countindirects(expr->data.cond.cond)) >= 2)
+ return 2;
+ if ((tmp2 = countindirects(expr->data.cond.expr1)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ if ((tmp2 = countindirects(expr->data.cond.expr2)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ return tmp1;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ return 2;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ if ((tmp1 = countindirects(expr->data.diadic.left)) >= 2)
+ return 2;
+ if ((tmp2 = countindirects(expr->data.diadic.right)) >= 2)
+ return 2;
+ if (tmp2 > tmp1)
+ tmp1 = tmp2;
+ return tmp1;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ if (expr->type == EINDIRECT)
+ return countindirects(expr->data.monadic) + 1;
+ else
+ return countindirects(expr->data.monadic);
+ default:
+ return 2;
+ }
+}
+
+static Boolean DetectCondSideAffect(ENode *expr) {
+ switch (expr->type) {
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ if (DetectCondSideAffect(expr->data.diadic.left))
+ return 1;
+ return DetectCondSideAffect(expr->data.diadic.right);
+ case EINDIRECT:
+ if (expr->data.monadic->type == EINDIRECT)
+ return 1;
+ if (expr->data.monadic->type == EOBJREF) {
+ if (expr->data.monadic->data.objref->datatype != DLOCAL && expr->data.monadic->data.objref->datatype != DDATA)
+ return 1;
+ if (IS_TYPE_POINTER(expr->data.monadic->data.objref->type))
+ return 1;
+ return Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister != 0;
+ }
+ return 1;
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ return DetectCondSideAffect(expr->data.monadic);
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ return 0;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOND:
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ case EMFPOINTER:
+ case ENULLCHECK:
+ case EPRECOMP:
+ case EDEFINE:
+ case EREUSE:
+ case EASSBLK:
+ case ECONDASS:
+ return 1;
+ default:
+ CError_FATAL(2523);
+ return 1;
+ }
+}
+
+static UInt8 WeightandSumOps(ENode *expr) {
+ UInt32 score;
+
+ switch (expr->type) {
+ case ECOND:
+ case ECONDASS:
+ score = WeightandSumOps(expr->data.cond.cond);
+ score += WeightandSumOps(expr->data.cond.expr1);
+ score += WeightandSumOps(expr->data.cond.expr2);
+ break;
+ case EMUL:
+ case EMULV:
+ case EMULASS:
+ score = WeightandSumOps(expr->data.diadic.left) + 10;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EDIV:
+ case EMODULO:
+ case EDIVASS:
+ case EMODASS:
+ score = WeightandSumOps(expr->data.diadic.left) + 20;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ score = WeightandSumOps(expr->data.diadic.left) + 1;
+ score += WeightandSumOps(expr->data.diadic.right);
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ score = WeightandSumOps(expr->data.monadic) + 1;
+ break;
+ case EINDIRECT:
+ if (expr->data.monadic->type == EOBJREF && expr->data.monadic->data.objref->datatype == DLOCAL)
+ if (!Registers_GetVarInfo(expr->data.monadic->data.objref)->noregister)
+ return 0;
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ score = WeightandSumOps(expr->data.monadic);
+ break;
+ case EOBJREF:
+ score = 0;
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EVECTOR128CONST:
+ score = 0;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ score = 5;
+ break;
+ default:
+ score = 255;
+ }
+
+ if (score >= 255)
+ score = 255;
+ return (UInt8) score;
+}
+
+Boolean TOC_use_fsel(ENode *expr) {
+ ENode *left;
+ ENode *right;
+ Type *rtype;
+ int score1;
+ int score2;
+
+ left = expr->data.cond.expr1;
+ right = expr->data.cond.expr2;
+ rtype = expr->rtype;
+
+ if (!copts.peephole) return 0;
+ if (!copts.gen_fsel) return 0;
+ if (left->hascall) return 0;
+ if (right->hascall) return 0;
+ if (!IS_TYPE_FLOAT(rtype)) return 0;
+ if (!IS_TYPE_FLOAT(left->rtype)) return 0;
+ if (!IS_TYPE_FLOAT(right->rtype)) return 0;
+
+ if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU)
+ return 0;
+ if (!IS_TYPE_FLOAT(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ if (expr->data.cond.cond->type == ELOGNOT || expr->data.cond.cond->type == ELAND || expr->data.cond.cond->type == ELOR)
+ return 0;
+
+ if (expr->type == ECONDASS) {
+ if (left->type != EINDIRECT)
+ return 0;
+ if (left->data.monadic->type != EOBJREF)
+ return 0;
+ }
+
+ if (DetectCondSideAffect(left))
+ return 0;
+ if (DetectCondSideAffect(right))
+ return 0;
+
+ if (expr->type == ECONDASS)
+ score1 = 1;
+ else
+ score1 = WeightandSumOps(left);
+ score2 = WeightandSumOps(right);
+
+ if (score1 > copts.gen_fsel)
+ return 0;
+ else if (score2 > copts.gen_fsel)
+ return 0;
+ else
+ return 1;
+}
+
+Boolean TOC_use_isel(ENode *expr, Boolean flag) {
+ int opt;
+ ENode *left;
+ ENode *right;
+ Type *rtype;
+ Object *obj;
+ int score1;
+ int score2;
+
+ left = expr->data.cond.expr1;
+ right = expr->data.cond.expr2;
+ rtype = expr->rtype;
+ if (flag)
+ opt = 10;
+ else
+ opt = copts.gen_isel;
+
+ if (!opt) return 0;
+ if (!copts.peephole) return 0;
+ if (left->hascall) return 0;
+ if (right->hascall) return 0;
+ if (!TYPE_FITS_IN_REGISTER(rtype)) return 0;
+ if (!TYPE_FITS_IN_REGISTER(left->rtype)) return 0;
+ if (!TYPE_FITS_IN_REGISTER(right->rtype)) return 0;
+
+ if (expr->data.cond.cond->type < ELESS || expr->data.cond.cond->type > ENOTEQU)
+ return 0;
+ if (TYPE_IS_8BYTES(rtype))
+ return 0;
+
+ if (flag) {
+ if (!TYPE_FITS_IN_REGISTER(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ if (TYPE_IS_8BYTES(expr->data.cond.cond->data.diadic.right->rtype))
+ return 0;
+ }
+
+ if (expr->type == ECONDASS) {
+ if (left->type != EINDIRECT)
+ return 0;
+ if (left->data.monadic->type != EOBJREF)
+ return 0;
+ if (flag) {
+ obj = left->data.monadic->data.objref;
+ if (obj->datatype != DLOCAL)
+ return 0;
+ if ((Registers_GetVarInfo(obj) ? Registers_GetVarInfo(obj)->reg : 0) == 0)
+ return 0;
+ if (obj->u.var.info->rclass != RegClass_GPR)
+ return 0;
+ }
+ }
+
+ if (DetectCondSideAffect(left))
+ return 0;
+ if (DetectCondSideAffect(right))
+ return 0;
+
+ if (expr->type == ECONDASS)
+ score1 = 1;
+ else
+ score1 = WeightandSumOps(left);
+ score2 = WeightandSumOps(right);
+
+ if (score1 > opt)
+ return 0;
+ else if (score2 > opt)
+ return 0;
+ else
+ return 1;
+}
+
+SInt32 GetSizeSkip(ENode *expr) {
+ if (expr->type == EASS)
+ expr = expr->data.diadic.right;
+ if (expr->type == ETYPCON && expr->data.monadic->rtype->size < expr->rtype->size)
+ return expr->data.monadic->rtype->size;
+ else
+ return expr->rtype->size;
+}
+
+void Optimize64bitMath(ENode *expr) {
+ ENode *left; // r23
+ ENode *right; // r28
+ SInt32 leftsize; // r24
+ SInt32 rightsize; // r25
+ SInt32 totalsize; // r22
+ int unsignedflag; // r4
+
+ CError_ASSERT(2886, TYPE_IS_8BYTES(expr->rtype));
+
+ left = expr->data.diadic.left;
+ right = expr->data.diadic.right;
+ leftsize = GetSizeSkip(left);
+ totalsize = (leftsize + (rightsize = GetSizeSkip(right)));
+ unsignedflag = is_unsigned(expr->rtype) != 0;
+
+ switch (totalsize) {
+ case 2:
+ case 3:
+ case 4:
+ if (unsignedflag) {
+ left->rtype = (Type *) &stunsignedint;
+ right->rtype = (Type *) &stunsignedint;
+ } else {
+ left->rtype = (Type *) &stsignedint;
+ right->rtype = (Type *) &stsignedint;
+ }
+ break;
+ case 5:
+ case 6:
+ case 8:
+ case 9:
+ case 10:
+ case 12:
+ if (expr->type != ESUB || leftsize >= rightsize) {
+ if (leftsize < 4) {
+ if (unsignedflag)
+ left->rtype = (Type *) &stunsignedint;
+ else
+ left->rtype = (Type *) &stsignedint;
+ } else {
+ if (left->type == ETYPCON && left->data.monadic->rtype != (Type *) &stfloat)
+ expr->data.diadic.left = left->data.monadic;
+ }
+ if (rightsize < 4) {
+ if (unsignedflag)
+ right->rtype = (Type *) &stunsignedint;
+ else
+ right->rtype = (Type *) &stsignedint;
+ } else {
+ if (right->type == ETYPCON && right->data.monadic->rtype != (Type *) &stfloat)
+ expr->data.diadic.right = right->data.monadic;
+ }
+ }
+ break;
+ case 16:
+ break;
+ default:
+ CError_FATAL(2975);
+ }
+}
+
+static Boolean OptimizeNestedAssginments(ENode **pexpr, Object *check) {
+ ENode *expr;
+ Boolean success1;
+ Boolean success2;
+
+ expr = *pexpr;
+ switch (expr->type) {
+ case EOBJREF:
+ return check != expr->data.objref;
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMODULO:
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case ECOMMA:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBCLR:
+ case EBTST:
+ case EBSET:
+ switch (expr->type) {
+ case EASS:
+ if (ENODE_IS(expr->data.diadic.left, EOBJREF) && expr->data.diadic.left->data.objref == check) {
+ *pexpr = expr->data.diadic.right;
+ return OptimizeNestedAssginments(pexpr, check);
+ }
+ break;
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ CError_FATAL(3033);
+ return 0;
+ }
+ if (OptimizeNestedAssginments(&expr->data.diadic.right, check))
+ return OptimizeNestedAssginments(&expr->data.diadic.left, check);
+ else
+ return 0;
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ return OptimizeNestedAssginments(&expr->data.monadic, check);
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EVECTOR128CONST:
+ return 1;
+ case ECOND:
+ success2 = OptimizeNestedAssginments(&expr->data.cond.expr2, check);
+ success1 = OptimizeNestedAssginments(&expr->data.cond.expr1, check);
+ if (!success2 || !success1)
+ return 0;
+ return OptimizeNestedAssginments(&expr->data.cond.cond, check) == 0;
+ case ECONDASS:
+ if (!OptimizeNestedAssginments(&expr->data.cond.expr2, check))
+ return 0;
+ if (OptimizeNestedAssginments(&expr->data.cond.cond, check))
+ return OptimizeNestedAssginments(&expr->data.cond.expr1, check) == 0;
+ else
+ return 0;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ case EMFPOINTER:
+ case ENULLCHECK:
+ case EPRECOMP:
+ case EDEFINE:
+ case EREUSE:
+ case EASSBLK:
+ return 0;
+ default:
+ CError_FATAL(3083);
+ return 0;
+ }
+}
+
+static void expandTOCexpression(ENode *expr, Type *type, int ignored) {
+ Object *obj;
+ Object *tmpobj;
+ ENode *cond;
+ ENode *tmpexpr;
+ ENode *newexpr;
+ ENodeList *list;
+
+ expr->ignored = ignored;
+ switch (expr->type) {
+ case EINTCONST:
+ expr->hascall = 0;
+ break;
+ case EFLOATCONST:
+ uses_globals = 1;
+ RewriteFloatConst(expr);
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ case EVECTOR128CONST:
+ if (!canoptimizevectorconst(&expr->data.vector128val, expr->rtype, NULL)) {
+ uses_globals = 1;
+ RewriteVectorConst(expr);
+ expandTOCexpression(expr, NULL, 0);
+ }
+ break;
+ case ESTRINGCONST:
+ uses_globals = 1;
+ CInit_RewriteString(expr, 1);
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ case EOBJREF:
+ obj = expr->data.objref;
+ CError_ASSERT(3203, obj->datatype != DALIAS);
+ if (obj->datatype == DFUNC || obj->datatype == DVFUNC)
+ uses_globals = 1;
+ if (obj->datatype == DDATA) {
+ uses_globals = 1;
+ if (createIndirect(obj, 0, 1)) {
+ tmpexpr = lalloc(sizeof(ENode));
+ memclrw(tmpexpr, sizeof(ENode));
+ tmpexpr->type = EOBJREF;
+ tmpexpr->cost = 0;
+ tmpexpr->data.objref = obj->toc;
+ tmpexpr->rtype = CDecl_NewPointerType(expr->rtype);
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->data.monadic = tmpexpr;
+ }
+ }
+ expr->hascall = 0;
+ break;
+ case ECONDASS:
+ expr->ignored = 0;
+ case ECOND:
+ if (!ENODE_IS_RANGE(expr->data.cond.cond, ELESS, ENOTEQU))
+ expr->data.cond.cond = comparewithzero(expr->data.cond.cond);
+ expandTOCexpression(expr->data.cond.expr1, NULL, ignored);
+ expandTOCexpression(expr->data.cond.expr2, NULL, ignored);
+ if (TOC_use_fsel(expr)) {
+ cond = expr->data.cond.cond;
+ if (ENODE_IS(cond->data.diadic.right, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.right->data.floatval)) {
+ expandTOCexpression(cond->data.diadic.left, NULL, 0);
+ } else if (ENODE_IS(cond->data.diadic.left, EFLOATCONST) && CMach_FloatIsZero(cond->data.diadic.left->data.floatval)) {
+ expandTOCexpression(cond->data.diadic.right, NULL, 0);
+ } else {
+ expandTOCexpression(expr->data.cond.cond, NULL, 0);
+ }
+ } else {
+ expandTOCexpression(expr->data.cond.cond, NULL, 0);
+ }
+ expr->hascall = expr->data.cond.cond->hascall | expr->data.cond.expr1->hascall | expr->data.cond.expr2->hascall;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ if (is_intrinsic_function_call(expr)) {
+ expr->hascall = 0;
+ if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_008) {
+ if (copts.altivec_model)
+ update_frame_align(16);
+ dynamic_stack = 1;
+ requires_frame = 1;
+ } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_035) {
+ if (expr->data.funccall.args->next->node->type == ESTRINGCONST) {
+ rewritestrcpy(expr);
+ } else {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+ } else if ((expr->data.funccall.funcref->data.objref->u.func.u.intrinsicid & 0xFFFFu) == Intrinsic_036) {
+ if (expr->data.funccall.args->next->next->node->type != EINTCONST) {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+ }
+ } else {
+ requires_frame = 1;
+ makes_call = 1;
+ expr->hascall = 1;
+ }
+
+ if (disables_optimizer(expr)) {
+ disable_optimizer |= 1;
+ if (copts.disable_registers)
+ disable_optimizer |= 2;
+ }
+
+ if (ENODE_IS(expr->data.funccall.funcref, EINDIRECT) && IS_TYPE_FUNC(expr->data.funccall.funcref->rtype))
+ *expr->data.funccall.funcref = *expr->data.funccall.funcref->data.monadic;
+
+ if (ENODE_IS(expr->data.funccall.funcref, EOBJREF)) {
+ expr->data.funccall.funcref->hascall = 0;
+ if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC && (expr->data.funccall.funcref->flags & ENODE_FLAG_80)) {
+ tmpobj = galloc(sizeof(Object));
+ *tmpobj = *expr->data.funccall.funcref->data.objref;
+ tmpobj->datatype = DFUNC;
+ expr->data.funccall.funcref->data.objref = tmpobj;
+ }
+ } else {
+ expandTOCexpression(expr->data.funccall.funcref, NULL, 0);
+ }
+
+ for (list = expr->data.funccall.args; list; list = list->next)
+ expandTOCexpression(list->node, NULL, 0);
+
+ if (expr->hascall)
+ estimate_func_param_size(expr);
+
+ if (is_intrinsic_function_call(expr)) {
+ for (list = expr->data.funccall.args; list; list = list->next)
+ expr->hascall |= list->node->hascall;
+ }
+
+ if (CMach_PassResultInHiddenArg(TYPE_FUNC(expr->data.funccall.functype)->functype))
+ rewritefunctioncallreturningstruct(expr);
+
+ break;
+ case ECOMMA:
+ expandTOCexpression(expr->data.diadic.left, NULL, 1);
+ expandTOCexpression(expr->data.diadic.right, NULL, ignored);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case ELAND:
+ case ELOR:
+ if (!ENODE_IS(expr->data.diadic.left, ELOGNOT) && !ENODE_IS2(expr->data.diadic.left, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.left, ELESS, ENOTEQU))
+ expr->data.diadic.left = comparewithzero(expr->data.diadic.left);
+ if (!ENODE_IS(expr->data.diadic.right, ELOGNOT) && !ENODE_IS2(expr->data.diadic.right, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.diadic.right, ELESS, ENOTEQU))
+ expr->data.diadic.right = comparewithzero(expr->data.diadic.right);
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case EDIVASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EDIV);
+ goto opassign_common;
+ case EMULASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EMUL);
+ goto opassign_common;
+ case EADDASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EADD);
+ goto opassign_common;
+ case ESUBASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, ESUB);
+ goto opassign_common;
+ case EMODASS:
+ if (!IS_TYPE_FLOAT(expr->rtype) && IS_TYPE_FLOAT(expr->data.diadic.right->rtype))
+ uses_globals = 1;
+ rewrite_opassign(expr, EMODULO);
+ goto opassign_common;
+ case ESHLASS:
+ rewrite_opassign(expr, ESHL);
+ goto opassign_common;
+ case ESHRASS:
+ rewrite_opassign(expr, ESHR);
+ goto opassign_common;
+ case EANDASS:
+ rewrite_opassign(expr, EAND);
+ goto opassign_common;
+ case EXORASS:
+ rewrite_opassign(expr, EXOR);
+ goto opassign_common;
+ case EORASS:
+ rewrite_opassign(expr, EOR);
+ goto opassign_common;
+ case EASS:
+ if (ENODE_IS(expr->data.diadic.left, EINDIRECT))
+ expr->data.diadic.left = expr->data.diadic.left->data.monadic;
+ opassign_common:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+ case EEQU:
+ case ENOTEQU:
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST) && expr->data.diadic.right->data.intval.lo == 0 && expr->data.diadic.right->data.intval.hi == 0) {
+ for (tmpexpr = expr->data.diadic.left; ENODE_IS2(tmpexpr, EFORCELOAD, ETYPCON); tmpexpr = tmpexpr->data.monadic) {
+ if (!TYPE_FITS_IN_REGISTER(tmpexpr->rtype))
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ELOGNOT) && TYPE_FITS_IN_REGISTER(tmpexpr->data.monadic->rtype)) {
+ if (ENODE_IS(expr, EEQU))
+ expr->type = ENOTEQU;
+ else
+ expr->type = EEQU;
+ expr->data.diadic.left = tmpexpr->data.monadic;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, EEQU)) {
+ if (ENODE_IS(expr, EEQU))
+ tmpexpr->type = ENOTEQU;
+ *expr = *tmpexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ENOTEQU)) {
+ if (ENODE_IS(expr, EEQU))
+ tmpexpr->type = EEQU;
+ *expr = *tmpexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ if (ENODE_IS(tmpexpr, ECOND)) {
+ newexpr = COND_to_COMPARE(tmpexpr->data.cond.cond, tmpexpr->data.cond.expr1, tmpexpr->data.cond.expr2);
+ if (newexpr) {
+ *tmpexpr = *newexpr;
+ expandTOCexpression(expr, NULL, 0);
+ break;
+ }
+ }
+ }
+ case EDIV:
+ if (ENODE_IS(expr, EDIV) && ENODE_IS(expr->data.diadic.right, EFLOATCONST) && CMach_FloatIsPowerOf2(expr->data.diadic.right->data.floatval)) {
+ expr->type = EMUL;
+ expr->data.diadic.right->data.floatval = CMach_FloatReciprocal(expr->data.diadic.right->data.floatval);
+ }
+ case EMODULO:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ if (TYPE_IS_8BYTES(expr->rtype)) {
+ if (ENODE_IS2(expr, ESHL, ESHR) && !ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ if (ENODE_IS2(expr, EDIV, EMODULO)) {
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ if (I8_log2n(((SInt64) expr->data.diadic.right->data.intval.hi << 32) + expr->data.diadic.right->data.intval.lo) <= 0) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ } else {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+ }
+ }
+ break;
+ case ESUB:
+ if (ENODE_IS(expr->data.diadic.right, EINTCONST)) {
+ expr->type = EADD;
+ expr->data.diadic.right->data.intval = CInt64_Neg(expr->data.diadic.right->data.intval);
+ }
+ case EMUL:
+ case EADD:
+ case EAND:
+ case EXOR:
+ case EOR:
+ expandTOCexpression(expr->data.diadic.left, type, 0);
+ expandTOCexpression(expr->data.diadic.right, type, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ if (ENODE_IS3(expr, EMUL, EADD, ESUB) && TYPE_IS_8BYTES(expr->rtype))
+ Optimize64bitMath(expr);
+ if (type) {
+ if (
+ ENODE_IS(expr->data.diadic.left, ETYPCON) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->rtype) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.left->data.monadic->rtype) &&
+ expr->data.diadic.left->data.monadic->rtype->size >= type->size &&
+ !TYPE_IS_8BYTES(expr->data.diadic.left->data.monadic->rtype)
+ )
+ expr->data.diadic.left = expr->data.diadic.left->data.monadic;
+
+ if (
+ ENODE_IS(expr->data.diadic.right, ETYPCON) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->rtype) &&
+ IS_TYPE_INT_OR_ENUM(expr->data.diadic.right->data.monadic->rtype) &&
+ expr->data.diadic.right->data.monadic->rtype->size >= type->size &&
+ !TYPE_IS_8BYTES(expr->data.diadic.right->data.monadic->rtype)
+ )
+ expr->data.diadic.right = expr->data.diadic.right->data.monadic;
+
+ expr->rtype = type;
+ }
+ break;
+
+ case ETYPCON:
+ tmpexpr = expr->data.monadic;
+ if ((IS_TYPE_INT_OR_ENUM(expr->rtype) && expr->rtype->size < 4) && IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && !TYPE_IS_8BYTES(tmpexpr->rtype)) {
+ expandTOCexpression(tmpexpr, expr->rtype, 0);
+ } else {
+ expandTOCexpression(tmpexpr, NULL, expr->rtype->type == TYPEVOID);
+ }
+
+ expr->hascall = tmpexpr->hascall;
+ if (IS_TYPE_INT_OR_ENUM(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype))
+ uses_globals = 1;
+
+ if ((TYPE_IS_8BYTES(tmpexpr->rtype) && IS_TYPE_FLOAT(expr->rtype)) || (TYPE_IS_8BYTES(expr->rtype) && IS_TYPE_FLOAT(tmpexpr->rtype))) {
+ uses_globals = 1;
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ }
+
+ if (IS_TYPE_FLOAT(tmpexpr->rtype)) {
+ if (is_unsigned(expr->rtype) && expr->rtype->size == 4) {
+ expr->hascall = 1;
+ requires_frame = 1;
+ makes_call = 1;
+ } else {
+ uses_globals = 1;
+ }
+ }
+
+ if (IS_TYPE_VECTOR(expr->rtype) && !IS_TYPE_VECTOR(tmpexpr->rtype))
+ PPCError_Error(PPCErrorStr114);
+ break;
+
+ case EPOSTINC:
+ if (!expr->ignored) {
+ if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype))
+ uses_globals = 1;
+ expandTOCexpression(expr->data.monadic, NULL, 0);
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+ }
+ expr->type = EPREINC;
+ case EPREINC:
+ rewrite_preincdec(expr);
+ rewrite_opassign(expr, EADD);
+ goto opassign_common;
+
+ case EPOSTDEC:
+ if (!expr->ignored) {
+ if (IS_TYPE_FLOAT(expr->data.monadic->rtype) && is_unsigned(expr->rtype))
+ uses_globals = 1;
+ expandTOCexpression(expr->data.monadic, NULL, 0);
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+ }
+ expr->type = EPREDEC;
+ case EPREDEC:
+ rewrite_preincdec(expr);
+ rewrite_opassign(expr, ESUB);
+ goto opassign_common;
+
+ case ELOGNOT:
+ if (!ENODE_IS(expr->data.monadic, ELOGNOT) && !ENODE_IS2(expr->data.monadic, ELAND, ELOR) && !ENODE_IS_RANGE(expr->data.monadic, ELESS, ENOTEQU))
+ expr->data.monadic = comparewithzero(expr->data.monadic);
+ case EMONMIN:
+ case EBINNOT:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, type, 0);
+ expr->hascall = tmpexpr->hascall;
+ if (type && ENODE_IS(expr->data.monadic, ETYPCON)) {
+ if (IS_TYPE_INT_OR_ENUM(expr->data.monadic->rtype) && IS_TYPE_INT_OR_ENUM(expr->data.monadic->data.monadic->rtype)) {
+ if (expr->data.monadic->data.monadic->rtype->size >= type->size) {
+ expr->data.monadic = expr->data.monadic->data.monadic;
+ expr->rtype = type;
+ }
+ }
+ }
+ break;
+
+ case EINDIRECT:
+ case EFORCELOAD:
+ case EBITFIELD:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, NULL, 0);
+ expr->hascall = tmpexpr->hascall;
+ break;
+
+ case EDEFINE:
+ tmpexpr = expr->data.monadic;
+ expandTOCexpression(tmpexpr, NULL, 0);
+ expr->hascall = tmpexpr->hascall;
+ break;
+
+ case EREUSE:
+ expr->hascall = expr->data.monadic->hascall;
+ break;
+
+ case ENULLCHECK:
+ expandTOCexpression(expr->data.diadic.left, NULL, 0);
+ expandTOCexpression(expr->data.diadic.right, NULL, 0);
+ expr->hascall = expr->data.diadic.left->hascall | expr->data.diadic.right->hascall;
+ break;
+
+ case EPRECOMP:
+ expr->hascall = 0;
+ break;
+
+ case ELABEL:
+ obj = createcodelabel(expr->data.label);
+ newexpr = lalloc(sizeof(ENode));
+ memclrw(newexpr, sizeof(ENode));
+ newexpr->type = EOBJREF;
+ newexpr->cost = 0;
+ newexpr->data.objref = obj;
+ newexpr->rtype = CDecl_NewPointerType(obj->type);
+
+ expr->type = EINDIRECT;
+ expr->cost = 1;
+ expr->data.monadic = newexpr;
+ expr->hascall = 0;
+ break;
+ }
+}
+
+static void checkexceptionreferences(ExceptionAction *action) {
+ for (; action; action = action->prev) {
+ switch (action->type) {
+ case EAT_DESTROYLOCAL:
+ referenceexception(action->data.destroy_local.local);
+ break;
+ case EAT_DESTROYLOCALCOND:
+ referenceexception(action->data.destroy_local_cond.local);
+ referenceexception(action->data.destroy_local_cond.cond);
+ break;
+ case EAT_DESTROYLOCALOFFSET:
+ referenceexception(action->data.destroy_local_offset.local);
+ break;
+ case EAT_DESTROYLOCALPOINTER:
+ referenceexception(action->data.destroy_local_pointer.pointer);
+ break;
+ case EAT_DESTROYLOCALARRAY:
+ referenceexception(action->data.destroy_local_array.localarray);
+ break;
+ case EAT_DESTROYBASE:
+ referenceexception(action->data.destroy_member.objectptr); // wrong union?
+ break;
+ case EAT_DESTROYPARTIALARRAY:
+ referenceexception(action->data.destroy_partial_array.arraypointer);
+ referenceexception(action->data.destroy_partial_array.arraycounter);
+ referenceexception(action->data.destroy_partial_array.element_size);
+ break;
+ case EAT_DESTROYMEMBER:
+ referenceexception(action->data.destroy_member.objectptr);
+ break;
+ case EAT_DESTROYMEMBERCOND:
+ referenceexception(action->data.destroy_member_cond.objectptr);
+ referenceexception(action->data.destroy_member_cond.cond);
+ break;
+ case EAT_DESTROYMEMBERARRAY:
+ referenceexception(action->data.destroy_member_array.objectptr);
+ break;
+ case EAT_DELETEPOINTER:
+ case EAT_DELETELOCALPOINTER:
+ referenceexception(action->data.delete_pointer.pointerobject);
+ break;
+ case EAT_DELETEPOINTERCOND:
+ referenceexception(action->data.delete_pointer_cond.pointerobject);
+ referenceexception(action->data.delete_pointer_cond.cond);
+ break;
+ case EAT_CATCHBLOCK:
+ referenceexception(action->data.catch_block.catch_object);
+ referenceexception(action->data.catch_block.catch_info_object);
+ break;
+ case EAT_ACTIVECATCHBLOCK:
+ referenceexception(action->data.active_catch_block.catch_info_object);
+ break;
+ }
+ }
+}
+
+void expandTOCreferences(Statement **stmts) {
+ Statement *stmt;
+ IAOperand *op;
+ int i;
+ InlineAsm *ia;
+ VarInfo *vi;
+
+ codelabellist = NULL;
+ exceptionlist = NULL;
+
+ for (stmt = *stmts; stmt; stmt = stmt->next) {
+ curstmtvalue = stmt->value;
+ if (stmt->flags & StmtFlag_1) {
+ has_catch_blocks = 1;
+ dynamic_stack = 1;
+ requires_frame = 1;
+ }
+
+ switch (stmt->type) {
+ case ST_EXPRESSION:
+ expandTOCexpression(stmt->expr, NULL, 1);
+ if (stmt->expr->type == ETYPCON && IS_TYPE_VOID(stmt->expr->rtype))
+ stmt->expr = stmt->expr->data.monadic;
+ break;
+ case ST_GOTOEXPR:
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ if (stmt->expr->type < ELESS || stmt->expr->type > ENOTEQU)
+ stmt->expr = comparewithzero(stmt->expr);
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_RETURN:
+ if (!stmt->expr)
+ continue;
+ expandTOCexpression(
+ stmt->expr, NULL,
+ IS_TYPE_ARRAY(stmt->expr->rtype) || IS_TYPE_NONVECTOR_STRUCT(stmt->expr->rtype) || IS_TYPE_CLASS(stmt->expr->rtype) ||
+ IS_TYPE_12BYTES_MEMBERPOINTER(stmt->expr->rtype));
+ break;
+ case ST_SWITCH:
+ uses_globals = 1;
+ expandTOCexpression(stmt->expr, NULL, 0);
+ break;
+ case ST_ENDCATCHDTOR:
+ requires_frame = 1;
+ makes_call = 1;
+ break;
+ case ST_ASM:
+ if ((ia = (InlineAsm *) stmt->expr)) {
+ if (ia->flags & IAFlag1) {
+ if (ia->opcode == IADirective_FrFree)
+ requires_frame = 1;
+ } else {
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ if (op->type == IAOpnd_Reg) {
+ if (!op->u.reg.object) {
+ if (op->u.reg.num == INVALID_PIC_REG)
+ uses_globals = 1;
+ else if (op->u.reg.effect & EffectWrite)
+ asm_used_register(op->u.reg.rclass, op->u.reg.num);
+ } else if ((vi = Registers_GetVarInfo(op->u.reg.object))) {
+ vi->flags |= VarInfoFlag40;
+ }
+ } else if (op->type == IAOpnd_3) {
+ uses_globals = 1;
+ }
+ }
+
+ if (ia->flags & IAFlag2)
+ makes_call = 1;
+ }
+ }
+ break;
+ }
+
+ checkexceptionreferences(stmt->dobjstack);
+ }
+}
+
+void resetTOCvarinfo(void) {
+ ObjectList *list;
+
+ for (list = toclist; list; list = list->next)
+ list->object->u.toc.info = CodeGen_GetNewVarInfo();
+}
+
+Boolean needdescriptor(void) {
+ // completely unused, dunno what args this might take
+ return 0;
+}
+
+Object *createstaticinitobject(void) {
+ char buf[100];
+ char *p;
+ Str255 fname;
+ TypeFunc *tfunc;
+ Object *obj;
+
+ COS_FileGetFSSpecInfo(&cparamblkptr->sourcefile, NULL, NULL, fname);
+ sprintf(buf, "__sinit_%*.*s", -fname[0], fname[0], &fname[1]);
+ for (p = &buf[1]; *p; p++) {
+ if (*p == '.')
+ *p = '_';
+ }
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ tfunc->type = TYPEFUNC;
+ tfunc->functype = &stvoid;
+ tfunc->args = NULL;
+ tfunc->flags = FUNC_DEFINED;
+
+ obj = galloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->otype = OT_OBJECT;
+ obj->type = (Type *) tfunc;
+ obj->name = GetHashNameNodeExport(buf);
+ obj->sclass = TK_STATIC;
+ obj->datatype = DFUNC;
+
+ return obj;
+}
+
+static void estimate_func_param_size(ENode *node) {
+ SInt32 work;
+ ENodeList *list;
+ SInt32 align;
+
+ work = 0;
+ for (list = node->data.funccall.args; list; list = list->next) {
+ align = ~7 & (CMach_ArgumentAlignment(list->node->rtype) + 7);
+ work += ~(align - 1) & (list->node->rtype->size + align - 1);
+ }
+
+ estimate_out_param_size(work);
+}