summaryrefslogtreecommitdiff
path: root/compiler_and_linker
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2022-11-20 00:07:22 -0500
committerAsh Wolf <ninji@wuffs.org>2022-11-20 00:07:22 -0500
commit9d2728a5605f651934fe67a6fe6986b3e4a2c011 (patch)
treee81e0a3588a0c8d1855bf28316efe27d86b04d66 /compiler_and_linker
parent9a46dd0e2e80790d9848c0bbd718932a27c23269 (diff)
downloadMWCC-9d2728a5605f651934fe67a6fe6986b3e4a2c011.tar.gz
MWCC-9d2728a5605f651934fe67a6fe6986b3e4a2c011.zip
add a bunch of code and a ton of stub files for later
Diffstat (limited to 'compiler_and_linker')
-rw-r--r--compiler_and_linker/FrontEnd/C/CPrep.c9
-rw-r--r--compiler_and_linker/unsorted/AddPropagation.c0
-rw-r--r--compiler_and_linker/unsorted/Alias.c0
-rw-r--r--compiler_and_linker/unsorted/BitVectors.c0
-rw-r--r--compiler_and_linker/unsorted/CABI.c2
-rw-r--r--compiler_and_linker/unsorted/CBrowse.c0
-rw-r--r--compiler_and_linker/unsorted/CClass.c61
-rw-r--r--compiler_and_linker/unsorted/CCompiler.c9
-rw-r--r--compiler_and_linker/unsorted/CException.c0
-rw-r--r--compiler_and_linker/unsorted/CExpr.c5170
-rw-r--r--compiler_and_linker/unsorted/CExpr2.c2421
-rw-r--r--compiler_and_linker/unsorted/CIRTransform.c0
-rw-r--r--compiler_and_linker/unsorted/CInline.c2
-rw-r--r--compiler_and_linker/unsorted/CMachine.c2
-rw-r--r--compiler_and_linker/unsorted/CObjC.c0
-rw-r--r--compiler_and_linker/unsorted/CObjCModern.c0
-rw-r--r--compiler_and_linker/unsorted/COptimizer.c1781
-rw-r--r--compiler_and_linker/unsorted/CPreprocess.c0
-rw-r--r--compiler_and_linker/unsorted/CRTTI.c0
-rw-r--r--compiler_and_linker/unsorted/CSOM.c0
-rw-r--r--compiler_and_linker/unsorted/CTemplateClass.c0
-rw-r--r--compiler_and_linker/unsorted/CTemplateFunc.c0
-rw-r--r--compiler_and_linker/unsorted/CTemplateNew.c0
-rw-r--r--compiler_and_linker/unsorted/CTemplateTools.c0
-rw-r--r--compiler_and_linker/unsorted/CodeGen.c1822
-rw-r--r--compiler_and_linker/unsorted/CodeGenOptPPC.c17
-rw-r--r--compiler_and_linker/unsorted/CodeMotion.c0
-rw-r--r--compiler_and_linker/unsorted/Coloring.c0
-rw-r--r--compiler_and_linker/unsorted/ConstantPropagation.c0
-rw-r--r--compiler_and_linker/unsorted/CopyPropagation.c0
-rw-r--r--compiler_and_linker/unsorted/Exceptions.c0
-rw-r--r--compiler_and_linker/unsorted/FuncLevelAsmPPC.c22
-rw-r--r--compiler_and_linker/unsorted/FunctionCalls.c0
-rw-r--r--compiler_and_linker/unsorted/GCCInlineAsm.c33
-rw-r--r--compiler_and_linker/unsorted/GenStabs.c0
-rw-r--r--compiler_and_linker/unsorted/GlobalOptimizer.c0
-rw-r--r--compiler_and_linker/unsorted/IROUseDef.c0
-rw-r--r--compiler_and_linker/unsorted/InlineAsm.c681
-rw-r--r--compiler_and_linker/unsorted/InlineAsmMnemonicsPPC.c1036
-rw-r--r--compiler_and_linker/unsorted/InlineAsmPPC.c2624
-rw-r--r--compiler_and_linker/unsorted/InlineAsmRegisters.c50
-rw-r--r--compiler_and_linker/unsorted/InlineAsmRegistersPPC.c854
-rw-r--r--compiler_and_linker/unsorted/InstrSelection.c4858
-rw-r--r--compiler_and_linker/unsorted/InterferenceGraph.c0
-rw-r--r--compiler_and_linker/unsorted/Intrinsics.c0
-rw-r--r--compiler_and_linker/unsorted/IrOptimizer.c0
-rw-r--r--compiler_and_linker/unsorted/IroBitVect.c114
-rw-r--r--compiler_and_linker/unsorted/IroCSE.c0
-rw-r--r--compiler_and_linker/unsorted/IroDump.c0
-rw-r--r--compiler_and_linker/unsorted/IroEmptyLoop.c0
-rw-r--r--compiler_and_linker/unsorted/IroEval.c0
-rw-r--r--compiler_and_linker/unsorted/IroExprRegeneration.c0
-rw-r--r--compiler_and_linker/unsorted/IroFlowgraph.c0
-rw-r--r--compiler_and_linker/unsorted/IroJump.c0
-rw-r--r--compiler_and_linker/unsorted/IroLinearForm.c0
-rw-r--r--compiler_and_linker/unsorted/IroLoop.c0
-rw-r--r--compiler_and_linker/unsorted/IroMalloc.c0
-rw-r--r--compiler_and_linker/unsorted/IroPointerAnalysis.c0
-rw-r--r--compiler_and_linker/unsorted/IroPropagate.c0
-rw-r--r--compiler_and_linker/unsorted/IroRangePropagation.c0
-rw-r--r--compiler_and_linker/unsorted/IroSubable.c0
-rw-r--r--compiler_and_linker/unsorted/IroTransform.c0
-rw-r--r--compiler_and_linker/unsorted/IroUnrollLoop.c0
-rw-r--r--compiler_and_linker/unsorted/IroUtil.c0
-rw-r--r--compiler_and_linker/unsorted/IroVars.c0
-rw-r--r--compiler_and_linker/unsorted/LoadDeletion.c0
-rw-r--r--compiler_and_linker/unsorted/LoopDetection.c0
-rw-r--r--compiler_and_linker/unsorted/LoopOptimization.c0
-rw-r--r--compiler_and_linker/unsorted/MachO.c0
-rw-r--r--compiler_and_linker/unsorted/ObjGenMachO.c0
-rw-r--r--compiler_and_linker/unsorted/Operands.c65
-rw-r--r--compiler_and_linker/unsorted/PCode.c28
-rw-r--r--compiler_and_linker/unsorted/PCodeAssembly.c0
-rw-r--r--compiler_and_linker/unsorted/PCodeInfo.c2
-rw-r--r--compiler_and_linker/unsorted/PCodeListing.c0
-rw-r--r--compiler_and_linker/unsorted/PPCError.c71
-rw-r--r--compiler_and_linker/unsorted/Peephole.c0
-rw-r--r--compiler_and_linker/unsorted/RegisterInfo.c30
-rw-r--r--compiler_and_linker/unsorted/Registers.c19
-rw-r--r--compiler_and_linker/unsorted/Scheduler.c0
-rw-r--r--compiler_and_linker/unsorted/SpillCode.c0
-rw-r--r--compiler_and_linker/unsorted/StackFrame.c6
-rw-r--r--compiler_and_linker/unsorted/StrengthReduction.c0
-rw-r--r--compiler_and_linker/unsorted/StructMoves.c0
-rw-r--r--compiler_and_linker/unsorted/Switch.c78
-rw-r--r--compiler_and_linker/unsorted/TOC.c8
-rw-r--r--compiler_and_linker/unsorted/Unmangle.c0
-rw-r--r--compiler_and_linker/unsorted/UseDefChains.c0
-rw-r--r--compiler_and_linker/unsorted/ValueNumbering.c0
-rw-r--r--compiler_and_linker/unsorted/VectorArraysToRegs.c0
90 files changed, 21563 insertions, 312 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CPrep.c b/compiler_and_linker/FrontEnd/C/CPrep.c
index 4e3ffea..4b66e88 100644
--- a/compiler_and_linker/FrontEnd/C/CPrep.c
+++ b/compiler_and_linker/FrontEnd/C/CPrep.c
@@ -46,15 +46,6 @@ static void gotonexttoken();
extern SInt16 *CLT_filesp;
extern CPrepFileInfo **CLT_filestack;
-//#define OPT_OFFSET(optname) ((short) (((char *) (&copts.optname)) - ((char *) &copts)))
-#define OPT_OFFSET(optname) ((short) ( &((COpts *)0)->optname ))
-enum {
- OPT_OFFSET_MASK = 0x1FFF,
- OPT_FLAG_2000 = 0x2000,
- OPT_FLAG_4000 = 0x4000,
- OPT_FLAG_8000 = 0x8000
-};
-
struct CompilerOption {
char *name;
short bits;
diff --git a/compiler_and_linker/unsorted/AddPropagation.c b/compiler_and_linker/unsorted/AddPropagation.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/AddPropagation.c
diff --git a/compiler_and_linker/unsorted/Alias.c b/compiler_and_linker/unsorted/Alias.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Alias.c
diff --git a/compiler_and_linker/unsorted/BitVectors.c b/compiler_and_linker/unsorted/BitVectors.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/BitVectors.c
diff --git a/compiler_and_linker/unsorted/CABI.c b/compiler_and_linker/unsorted/CABI.c
index 0b29b9d..e903797 100644
--- a/compiler_and_linker/unsorted/CABI.c
+++ b/compiler_and_linker/unsorted/CABI.c
@@ -9,7 +9,7 @@ static void *cabi_pathcur; // TODO type
static TypeClass *cabi_loop_class;
static Boolean cabi_loop_construct;
-short CABI_GetStructResultArgumentIndex(void) {
+short CABI_GetStructResultArgumentIndex(TypeFunc *tfunc) {
return 0;
}
diff --git a/compiler_and_linker/unsorted/CBrowse.c b/compiler_and_linker/unsorted/CBrowse.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CBrowse.c
diff --git a/compiler_and_linker/unsorted/CClass.c b/compiler_and_linker/unsorted/CClass.c
index 7932586..0d2091b 100644
--- a/compiler_and_linker/unsorted/CClass.c
+++ b/compiler_and_linker/unsorted/CClass.c
@@ -1,4 +1,11 @@
#include "compiler/CClass.h"
+#include "compiler/CError.h"
+#include "compiler/CInline.h"
+#include "compiler/CMangler.h"
+#include "compiler/CParser.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CodeGen.h"
+#include "compiler/objects.h"
typedef struct OVClassBase {
struct OVClassBase *next;
@@ -23,8 +30,17 @@ typedef struct OVClass {
Boolean alloced_vtable;
} OVClass;
+typedef struct ThunkList {
+ struct ThunkList *next;
+ Object *thunkobj;
+ Object *obj;
+ SInt32 a;
+ SInt32 b;
+ SInt32 c;
+} ThunkList;
+
static TypeClass *main_class;
-static void *cclass_thunklist; // TODO type
+static ThunkList *cclass_thunklist;
static TypeClass *cclass_isbase_mostderived;
static void *cclass_isbase_foundoffset; // TODO type
static Boolean cclass_isambigbase;
@@ -45,8 +61,45 @@ static SInt32 cclass_dominator_ooffset;
static Object *cclass_dominator_eobject;
void CClass_Init(void) {}
-void CClass_GenThunks(void) {}
-static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) {}
+
+void CClass_GenThunks(void) {
+ ThunkList *list;
+
+ for (list = cclass_thunklist; list; list = list->next) {
+ list->obj->flags |= OBJECT_FLAGS_4;
+ CodeGen_GenVDispatchThunk(list->thunkobj, list->obj, list->a, list->b, list->c);
+ }
+}
+
+static Object *CClass_ThunkObject(Object *obj, SInt32 a, SInt32 b, SInt32 c) {
+ Object *thunkobj;
+ ThunkList *list;
+
+ CInline_ObjectAddrRef(obj);
+ for (list = cclass_thunklist; list; list = list->next) {
+ if (obj == list->obj && a == list->a && b == list->b && c == list->c)
+ return list->thunkobj;
+ }
+
+ thunkobj = CParser_NewCompilerDefFunctionObject();
+ thunkobj->name = CMangler_ThunkName(obj, a, b, c);
+ thunkobj->type = TYPE(&rt_func);
+ thunkobj->sclass = TK_EXTERN;
+ thunkobj->qual = Q_20000;
+ thunkobj->u.func.linkname = thunkobj->name;
+
+ list = galloc(sizeof(ThunkList));
+ list->thunkobj = thunkobj;
+ list->obj = obj;
+ list->a = a;
+ list->b = b;
+ list->c = c;
+ list->next = cclass_thunklist;
+ cclass_thunklist = list;
+
+ return thunkobj;
+}
+
static Boolean CClass_IsZeroOffsetClass(TypeClass *a, TypeClass *b) {}
static UInt8 CClass_IsCovariantResult(Type *a, UInt32 qualA, Type *b, UInt32 qualB) {}
UInt8 CClass_GetOverrideKind(TypeFunc *a, TypeFunc *b, Boolean errorflag) {}
@@ -58,7 +111,7 @@ ENode *CClass_DefaultConstructorCall(TypeClass *a, TypeClass *b, ENode *expr, SI
Object *CClass_AssignmentOperator(TypeClass *tclass) {}
Object *CClass_CopyConstructor(TypeClass *tclass) {}
NameSpaceObjectList *CClass_MemberObject(TypeClass *tclass, HashNameNode *name) {}
-Object *CClass_Constructor(TypeClass *tclass) {}
+NameSpaceObjectList *CClass_Constructor(TypeClass *tclass) {}
Object *CClass_Destructor(TypeClass *tclass) {}
Boolean CClass_IsConstructor(Object *obj) {}
Boolean CClass_IsDestructor(Object *obj) {}
diff --git a/compiler_and_linker/unsorted/CCompiler.c b/compiler_and_linker/unsorted/CCompiler.c
index 8339cf6..6159517 100644
--- a/compiler_and_linker/unsorted/CCompiler.c
+++ b/compiler_and_linker/unsorted/CCompiler.c
@@ -1,9 +1,10 @@
-#include "compiler/common.h"
-#include "compiler.h"
+#include "compiler/CCompiler.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CodeGen.h"
#include "compiler/types.h"
#include "pref_structs.h"
-#include "compiler/CompilerTools.h"
-#include "compiler/CPrep.h"
Boolean systemHandles;
diff --git a/compiler_and_linker/unsorted/CException.c b/compiler_and_linker/unsorted/CException.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CException.c
diff --git a/compiler_and_linker/unsorted/CExpr.c b/compiler_and_linker/unsorted/CExpr.c
index e73c4bb..9968bab 100644
--- a/compiler_and_linker/unsorted/CExpr.c
+++ b/compiler_and_linker/unsorted/CExpr.c
@@ -1,123 +1,5057 @@
#include "compiler/CExpr.h"
+#include "compiler/CABI.h"
+#include "compiler/CClass.h"
+#include "compiler/CDecl.h"
#include "compiler/CError.h"
+#include "compiler/CInit.h"
+#include "compiler/CInline.h"
+#include "compiler/CMachine.h"
+#include "compiler/CMangler.h"
+#include "compiler/CInt64.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/templates.h"
-Boolean (*name_obj_check)(void *, Object *); // TODO figure out the right type
+Boolean (*name_obj_check)(HashNameNode *, Object *);
Boolean disallowgreaterthan;
-void CExpr_RewriteConst() {}
-void optimizecomm() {}
-static void checkadditive() {}
-static void CExpr_CompareConvert() {}
-static void CExpr_ConstResult() {}
-static void makemultnode() {}
-static void makedivnode() {}
-static void canadd2() {}
-void canadd() {}
-static void addconst() {}
-static void integralpointerpromote() {}
-static void padd() {}
-static void psub() {}
-static void makeaddnode() {}
-static void makesubnode() {}
-void checkreference() {}
-static ENode *pointer_generation2(ENode *expr) {}
-ENode *pointer_generation(ENode *expr) {}
-void CExpr_PointerGeneration() {}
-static void CExpr_ConstPointerCheck() {}
-void oldassignmentpromotion() {}
-void argumentpromotion() {}
-void classargument() {}
-ENodeList *CExpr_ScanExpressionList(Boolean flag) {}
-static void skipcommaexpr() {}
-void CExpr_DoExplicitConversion() {}
-static void CExpr_TemplArgDepCast() {}
-static void CExpr_ParseExplicitConversion() {}
-static void CExpr_MemberVarAccess() {}
-static void CExpr_IsTemplateFunc() {}
-static void CExpr_ExplicitTemplateArgCheck() {}
-void CExpr_MakeNameLookupResultExpr() {}
-static void CExpr_NewPTMType() {}
-static void CExpr_ParseNameResultExpr() {}
-static void CExpr_ParseRotate() {}
-static void CExpr_ParseNextArg() {}
-static void CExpr_ParseVecStep() {}
-static void CExpr_BuiltInComputeAlign() {}
-static void CExpr_AtomTypeID() {}
-static void CExpr_BuiltInComputeType() {}
-static void CExpr_BuiltInClassifyType() {}
-static void CExpr_BuiltInComputeVArgType() {}
-static void CExpr_ParseTypeExpression() {}
-static void CExpr_ParseBuiltin() {}
-static void CExpr_ParseBuiltin_isintconst() {}
-static void primary_expression() {}
-static void CExpr_SimpleExplicitConversion() {}
-static void CExpr_NewPTMFCall() {}
-static void call_ptmf() {}
-static void CExpr_DummyDestr() {}
-static void postfix_expression() {}
-static void CExpr_ParseSizeof() {}
-void scansizeof() {}
-static void CExpr_ParseAlignof() {}
-void scanalignof() {}
-static void logicalexpression() {}
-void getnodeaddress() {}
-static void CExpr_MakeStaticMemberList() {}
-static void CExpr_MakePTDM() {}
-void getpointertomemberfunc() {}
-static void getpointertomember() {}
-void CExpr_New_ELOGNOT_Node() {}
-void CExpr_New_EMONMIN_Node() {}
-void CExpr_New_EBINNOT_Node() {}
-void unary_expression() {}
-void do_castnullcheck() {}
-void CExpr_SafeClassPointerCast() {}
-void PointerToMemberCast() {}
-void CExpr_MemberPointerConversion() {}
-static void CExpr_MemberPointerCast() {}
-void do_typecast() {}
-static void isvectorconst() {}
-void cast_expression() {}
-static void pm_expression() {}
-void CExpr_New_EMUL_Node() {}
-void CExpr_New_EDIV_Node() {}
-void CExpr_New_EMODULO_Node() {}
-void CExpr_New_EADD_Node() {}
-void CExpr_New_ESUB_Node() {}
-void CExpr_New_ESHL_Node() {}
-void CExpr_New_ESHR_Node() {}
-static void pointercompare() {}
-static void unsigncheck() {}
-void CExpr_New_ELESS_Node() {}
-void CExpr_New_ELESSEQU_Node() {}
-void CExpr_New_EGREATER_Node() {}
-void CExpr_New_EGREATEREQU_Node() {}
-void memberpointercompare() {}
-void CExpr_New_EEQU_Node() {}
-void CExpr_New_ENOTEQU_Node() {}
-void CExpr_New_EAND_Node() {}
-void CExpr_New_EXOR_Node() {}
-void CExpr_New_EOR_Node() {}
-void CExpr_New_ELAND_Node() {}
-void CExpr_New_ELOR_Node() {}
-void CExpr_NewDyadicNode() {}
-static void CExpr_GetDyadicInfo() {}
-static void CExpr_ParseDyadicExpression() {}
-static void CExpr_IsBlockMoveType() {}
-void CExpr_New_ECOND_Node() {}
-static void conditional_expression() {}
-static void CExpr_MakeOpAssNode() {}
-static void makeassignmentnode() {}
-static void makepassignmentnode() {}
-static void makemulassignmentnode() {}
-static void CExpr_TransformOpAssign() {}
-ENode *assignment_expression(void) {}
-ENode *conv_assignment_expression(void) {}
-static void CExpr_HasSideEffect() {}
-void CExpr_CheckUnusedExpression() {}
-void s_expression() {}
-ENode *expression(void) {}
-void CExpr_IntegralConstExprType() {}
-ENode *CExpr_IntegralConstOrDepExpr(void) {}
-void CExpr_IntegralConstExpr() {}
-void CExpr_CheckUnwantedAssignment() {}
-void CExpr_ParseAsmExpr() {}
+// MOVE ME
+extern ENode *CIRTrans_TransformOpAss(ENode *);
+extern ENode *CTempl_MakeTemplDepExpr(ENode *, ENodeType, ENode *);
+extern Boolean CTemplTool_IsTemplateArgumentDependentType(Type *type);
+extern Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr);
+extern ENode *CSOM_MemberVarAccess(BClassList *path, ObjMemberVar *var, ENode *expr);
+extern TemplArg *CTempl_ParseUncheckTemplArgs(void *a, Boolean flag);
+extern Boolean CObjC_IsCompatibleType(Type *a, Type *b);
+extern Type *CObjC_GetObjCType_id(Boolean flag);
+extern ENode *CExcept_ScanThrowExpression(void);
+extern void PPCError_Error(int code, ...);
+extern ENode *CObjC_ParseSelectorExpression(void);
+extern ENode *CObjC_ParseEncodeExpression(void);
+extern ENode *CObjC_ParseProtocolExpression(void);
+extern ENode *CObjC_ParseAtExpression(void);
+extern ENode *CObjC_ParseMessageExpression(void);
+extern ENode *CRTTI_Parse_const_cast(void);
+extern ENode *CRTTI_Parse_dynamic_cast(void);
+extern ENode *CRTTI_Parse_reinterpret_cast(void);
+extern ENode *CRTTI_Parse_static_cast(void);
+extern ENode *CRTTI_ParseTypeID(void);
+extern Boolean CObjC_IsType_id(Type *type);
+extern ENode *CObjC_CheckModernSendMessage(Type *type, ENode *expr);
+
+// forward declarations
+static ENode *makeaddnode(ENode *left, ENode *right);
+static ENode *makesubnode(ENode *left, ENode *right);
+
+ENode *CExpr_RewriteConst(ENode *expr) {
+ Object *obj;
+
+restart:
+ if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EOBJREF)) {
+ obj = expr->data.monadic->data.objref;
+ if (obj->datatype == DALIAS) {
+ CExpr_AliasTransform(expr->data.monadic);
+ goto restart;
+ }
+
+ if ((obj->qual & Q_10000) && expr->rtype == obj->type) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEENUM:
+ expr->type = EINTCONST;
+ expr->data.intval = obj->u.data.u.intconst;
+ break;
+ case TYPEPOINTER:
+ expr->type = EINTCONST;
+ expr->data.intval = obj->u.data.u.intconst;
+ expr->rtype = TYPE(&stunsignedlong);
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = obj->type;
+ break;
+ case TYPEFLOAT:
+ expr->type = EFLOATCONST;
+ if (obj->u.data.u.floatconst)
+ expr->data.floatval = *obj->u.data.u.floatconst;
+ else
+ expr->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), cint64_zero);
+ break;
+ default:
+#line 105
+ CError_FATAL();
+ }
+ }
+ }
+
+ return expr;
+}
+
+void optimizecomm(ENode *expr) {
+ ENode *right;
+ ENode *left;
+
+ if (ENODE_IS((right = expr->data.diadic.right), EINTCONST))
+ return;
+ if (ENODE_IS((left = expr->data.diadic.left), EINTCONST)) {
+ swap:
+ expr->data.diadic.right = left;
+ expr->data.diadic.left = right;
+ return;
+ }
+
+ if (ENODE_IS(left, EFLOATCONST))
+ return;
+ if (ENODE_IS(right, EFLOATCONST))
+ goto swap;
+
+ if (expr->rtype->type > TYPEFLOAT)
+ return;
+
+ if (left->cost > right->cost)
+ goto swap;
+}
+
+static void checkadditive(ENode *expr) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ if (expr->rtype == TYPE(&stbool))
+ break;
+ case TYPEFLOAT:
+ return;
+ case TYPEENUM:
+ if (copts.cplusplus)
+ break;
+ return;
+ case TYPEPOINTER:
+ if (TPTR_TARGET(expr->rtype)->size == 0)
+ CDecl_CompleteType(TPTR_TARGET(expr->rtype));
+ if (TPTR_TARGET(expr->rtype)->size == 0)
+ break;
+ return;
+ case TYPEARRAY:
+ if (ENODE_IS(expr, EOBJREF))
+ return;
+ }
+
+ CError_Error(CErrorStr376, expr->rtype, ENODE_QUALS(expr));
+}
+
+static void CExpr_CompareConvert(ENode **leftp, char *opname, ENode **rightp, Boolean flag) {
+ ENode *left;
+ ENode *right;
+ CInt64 val;
+
+ left = *leftp;
+ right = *rightp;
+
+ switch (left->rtype->type) {
+ case TYPEINT:
+ break;
+ case TYPEFLOAT:
+ if (left->rtype != right->rtype)
+ CExpr_ArithmeticConversion(leftp, rightp);
+ return;
+ case TYPEENUM:
+ left->rtype = TYPE_ENUM(left->rtype)->enumtype;
+ break;
+ default:
+ CError_Error(CErrorStr377,
+ left->rtype, ENODE_QUALS(left),
+ opname,
+ right->rtype, ENODE_QUALS(right));
+ left = nullnode();
+ }
+
+ switch (right->rtype->type) {
+ case TYPEINT:
+ break;
+ case TYPEFLOAT:
+ CExpr_ArithmeticConversion(leftp, rightp);
+ return;
+ case TYPEENUM:
+ right->rtype = TYPE_ENUM(right->rtype)->enumtype;
+ break;
+ default:
+ CError_Error(CErrorStr377,
+ left->rtype, ENODE_QUALS(left),
+ opname,
+ right->rtype, ENODE_QUALS(right));
+ right = nullnode();
+ }
+
+ if (left->rtype == right->rtype) {
+ *leftp = left;
+ *rightp = right;
+ return;
+ }
+
+ if (left->rtype->size == right->rtype->size) {
+ if (is_unsigned(left->rtype) == is_unsigned(right->rtype)) {
+ left->rtype = right->rtype;
+ *leftp = left;
+ *rightp = right;
+ return;
+ }
+ } else {
+ if (ENODE_IS(right, EINTCONST) && left->rtype->size <= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(left->rtype))) {
+ val = CMach_CalcIntDiadic(left->rtype, right->data.intval, '+', cint64_zero);
+ val = CMach_CalcIntDiadic(right->rtype, val, '+', cint64_zero);
+ if (CInt64_Equal(val, right->data.intval)) {
+ right->rtype = left->rtype;
+ *leftp = left;
+ *rightp = right;
+ return;
+ }
+ }
+
+ if (ENODE_IS(left, EINTCONST) && left->rtype->size >= right->rtype->size && (is_unsigned(left->rtype) == is_unsigned(right->rtype) || is_unsigned(right->rtype))) {
+ val = CMach_CalcIntDiadic(right->rtype, left->data.intval, '+', cint64_zero);
+ val = CMach_CalcIntDiadic(left->rtype, val, '+', cint64_zero);
+ if (CInt64_Equal(val, left->data.intval)) {
+ left->rtype = right->rtype;
+ *leftp = left;
+ *rightp = right;
+ return;
+ }
+ }
+ }
+
+ *leftp = left;
+ *rightp = right;
+ CExpr_ArithmeticConversion(leftp, rightp);
+}
+
+static ENode *CExpr_ConstResult(ENode *expr, SInt32 value) {
+ ENode *constnode;
+
+ if (IS_TYPE_FLOAT(expr->rtype)) {
+ constnode = intconstnode(TYPE(&stsignedint), value);
+ constnode->type = EFLOATCONST;
+ constnode->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedint), constnode->data.intval);
+ constnode->rtype = expr->rtype;
+ } else {
+ constnode = intconstnode(expr->rtype, value);
+ }
+
+ if (CInline_ExpressionHasSideEffect(expr))
+ return makediadicnode(expr, constnode, ECOMMA);
+ else
+ return constnode;
+}
+
+static ENode *makemultnode(ENode *left, ENode *right) {
+ CExpr_ArithmeticConversion(&left, &right);
+ if (iszero(left))
+ return CExpr_ConstResult(right, 0);
+ if (iszero(right))
+ return CExpr_ConstResult(left, 0);
+
+ if (CExpr_IsOne(right))
+ return left;
+ if (CExpr_IsOne(left))
+ return right;
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '*', right->data.intval);
+ return left;
+ }
+ if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '*', right->data.floatval);
+ return left;
+ }
+
+ left = makediadicnode(left, right, EMUL);
+ optimizecomm(left);
+ if (IS_TYPE_INT(left->rtype) && left->rtype->size > 2) {
+ left->cost++;
+ if (left->cost > 200)
+ left->cost = 200;
+ }
+
+ if (IS_TYPE_FLOAT(left->rtype))
+ left = CExpr_BinaryFloatExpression(left);
+
+ return left;
+}
+
+static ENode *makedivnode(ENode *left, ENode *right, Boolean no_warning) {
+ CExpr_ArithmeticConversion(&left, &right);
+ if (iszero(right) && IS_TYPE_INT(right->rtype)) {
+ if (!no_warning)
+ CError_Warning(CErrorStr139);
+ return right;
+ }
+
+ if (CExpr_IsOne(right))
+ return left;
+
+ if (iszero(left) && IS_TYPE_INT(left->rtype))
+ return CExpr_ConstResult(right, 0);
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '/', right->data.intval);
+ return left;
+ }
+ if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '/', right->data.floatval);
+ return left;
+ }
+
+ left = makediadicnode(left, right, EDIV);
+ if (IS_TYPE_FLOAT(left->rtype))
+ left = CExpr_BinaryFloatExpression(left);
+
+ return left;
+}
+
+static short canadd2(ENode *expr, CInt64 value) {
+ Float tmp;
+
+ if (CInt64_IsZero(&value))
+ return 1;
+
+ switch (expr->type) {
+ case EINTCONST:
+ expr->data.intval = CMach_CalcIntDiadic(expr->rtype, expr->data.intval, '+', value);
+ return 1;
+ case EFLOATCONST:
+ tmp = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), value);
+ expr->data.floatval = CMach_CalcFloatDiadic(expr->rtype, expr->data.floatval, '+', tmp);
+ return 1;
+ case EADD:
+ if (canadd2(expr->data.diadic.left, value))
+ return 1;
+ if (canadd2(expr->data.diadic.right, value))
+ return 1;
+ return 0;
+ case ESUB:
+ if (canadd2(expr->data.diadic.left, value))
+ return 1;
+ if (canadd2(expr->data.diadic.right, CInt64_Neg(value)))
+ return 1;
+ return 0;
+ case ETYPCON:
+ if (IS_TYPE_POINTER_ONLY(expr->rtype) && ENODE_IS(expr->data.monadic, EINTCONST)) {
+ expr->data.monadic->data.intval = CMach_CalcIntDiadic(TYPE(&stunsignedlong), expr->data.monadic->data.intval, '+', value);
+ return 1;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+short canadd(ENode *expr, SInt32 value) {
+ CInt64 value64;
+ CInt64_SetLong(&value64, value);
+ return canadd2(expr, value64);
+}
+
+static ENode *addconst(ENode *expr, SInt32 value) {
+ ENode *right;
+
+ if (canadd(expr, value))
+ return expr;
+
+ if (stsignedint.size < 4 && (value > 0x7FFF || value < -0x8000))
+ right = intconstnode(TYPE(&stsignedlong), value);
+ else
+ right = intconstnode(TYPE(&stsignedint), value);
+
+ CExpr_ArithmeticConversion(&expr, &right);
+ expr = makediadicnode(expr, right, EADD);
+ return expr;
+}
+
+static ENode *integralpointerpromote(ENode *expr) {
+ Boolean uns;
+ Type *type;
+
+ if (!IS_TYPE_INT(expr->rtype))
+ expr = forceintegral(expr);
+
+ if (expr->rtype->size != 4) {
+ type = TYPE(&stunsignedlong);
+ if (is_unsigned(type) != (uns = is_unsigned(expr->rtype))) {
+ if (uns) {
+ if (stunsignedlong.size == 4) {
+ type = TYPE(&stunsignedlong);
+ } else if (stunsignedint.size == 4) {
+ type = TYPE(&stunsignedint);
+ } else {
+#line 480
+ CError_FATAL();
+ }
+ } else {
+ if (stsignedlong.size == 4) {
+ type = TYPE(&stsignedlong);
+ } else if (stsignedint.size == 4) {
+ type = TYPE(&stsignedint);
+ } else {
+#line 486
+ CError_FATAL();
+ }
+ }
+ }
+
+ if (ENODE_IS(expr, EINTCONST))
+ expr->data.intval = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval);
+ else
+ expr = makemonadicnode(expr, ETYPCON);
+
+ expr->rtype = type;
+ }
+
+ return expr;
+}
+
+static ENode *padd(ENode *left, ENode *right) {
+ Type *innertype;
+ SInt32 innersize;
+ ENode *expr;
+
+ right = integralpointerpromote(right);
+ innertype = TPTR_TARGET(left->rtype);
+ innersize = innertype->size;
+ if (innersize == 0) {
+ CDecl_CompleteType(innertype);
+ innersize = innertype->size;
+ if (innersize == 0) {
+ CError_Error(CErrorStr146);
+ return left;
+ }
+ }
+
+ expr = makemultnode(
+ right,
+ intconstnode((innersize > 0x7FFF) ? TYPE(&stsignedlong) : TYPE(&stsignedint), innersize));
+
+ if (ENODE_IS(expr, EINTCONST) && canadd2(left, expr->data.intval))
+ return left;
+
+ if (ENODE_IS(left, EADD) && ENODE_IS(left->data.diadic.right, EINTCONST)) {
+ left->data.diadic.left = makediadicnode(left->data.diadic.left, expr, EADD);
+ return left;
+ }
+
+ expr = makediadicnode(left, expr, EADD);
+ expr->rtype = left->rtype;
+ expr->flags = left->flags;
+ return expr;
+}
+
+static ENode *psub(ENode *left, ENode *right) {
+ Type *innertype;
+ SInt32 innersize;
+ ENode *expr;
+
+ if (IS_TYPE_POINTER(right->rtype)) {
+ innersize = TPTR_TARGET(left->rtype)->size;
+ if (innersize == 0) {
+ CDecl_CompleteType(TPTR_TARGET(left->rtype));
+ innersize = TPTR_TARGET(left->rtype)->size;
+ if (innersize == 0) {
+ CError_Error(CErrorStr146);
+ return left;
+ }
+ }
+
+ if (!is_typeequal(left->rtype, right->rtype)) {
+ CError_Error(CErrorStr245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ return left;
+ }
+
+ if (ENODE_IS(left, ETYPCON) && ENODE_IS(left->data.monadic, EINTCONST) && ENODE_IS(right, ETYPCON) && ENODE_IS(right->data.monadic, EINTCONST)) {
+ left->data.monadic->rtype = right->data.monadic->rtype = CABI_GetPtrDiffTType();
+ expr = makesubnode(left->data.monadic, right->data.monadic);
+ if (innersize > 1)
+ expr = makedivnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), 11);
+ return expr;
+ }
+
+ expr = makediadicnode(left, right, ESUB);
+ expr->rtype = CABI_GetPtrDiffTType();
+ if (innersize > 1)
+ expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), innersize), EDIV);
+ return expr;
+ }
+
+ right = integralpointerpromote(right);
+ innertype = TPTR_TARGET(left->rtype);
+ innersize = innertype->size;
+ if (innersize == 0) {
+ CDecl_CompleteType(innertype);
+ innersize = innertype->size;
+ if (innersize == 0) {
+ CError_Error(CErrorStr146);
+ return left;
+ }
+ }
+
+ expr = makemultnode(right, intconstnode(CABI_GetPtrDiffTType(), innersize));
+ if (ENODE_IS(expr, EINTCONST) && canadd2(left, CInt64_Neg(expr->data.intval)))
+ return left;
+
+ expr = makediadicnode(left, expr, ESUB);
+ expr->rtype = left->rtype;
+ expr->flags = left->flags;
+ return expr;
+}
+
+static ENode *makeaddnode(ENode *left, ENode *right) {
+ if (IS_TYPE_POINTER(left->rtype))
+ return padd(left, right);
+ if (IS_TYPE_POINTER(right->rtype))
+ return padd(right, left);
+
+ CExpr_ArithmeticConversion(&left, &right);
+ if (iszero(right))
+ return left;
+ if (iszero(left))
+ return right;
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '+', right->data.intval);
+ return left;
+ }
+ if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '+', right->data.floatval);
+ return left;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && canadd2(right, left->data.intval))
+ return right;
+ if (ENODE_IS(right, EINTCONST) && canadd2(left, right->data.intval))
+ return left;
+
+ left = makediadicnode(left, right, EADD);
+ optimizecomm(left);
+ if (IS_TYPE_FLOAT(left->rtype))
+ left = CExpr_BinaryFloatExpression(left);
+ return left;
+}
+
+static ENode *makesubnode(ENode *left, ENode *right) {
+ if (ENODE_IS(right, EINTCONST) && !is_unsigned(right->rtype) && !IS_TYPE_FLOAT(left->rtype)) {
+ right->data.intval = CInt64_Neg(right->data.intval);
+ return makeaddnode(left, right);
+ }
+
+ if (IS_TYPE_POINTER(left->rtype))
+ return psub(left, right);
+
+ CExpr_ArithmeticConversion(&left, &right);
+ if (iszero(right))
+ return left;
+ if (iszero(left)) {
+ if (ENODE_IS(right, EINTCONST)) {
+ right->data.intval = CInt64_Neg(right->data.intval);
+ return right;
+ }
+ if (ENODE_IS(right, EFLOATCONST)) {
+ right->data.floatval = CMach_CalcFloatMonadic(right->rtype, '-', right->data.floatval);
+ return right;
+ }
+ return CExpr_UnaryFloatExpression(makemonadicnode(right, EMONMIN));
+ }
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '-', right->data.intval);
+ return left;
+ }
+ if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ left->data.floatval = CMach_CalcFloatDiadic(left->rtype, left->data.floatval, '-', right->data.floatval);
+ return left;
+ }
+
+ if (ENODE_IS(right, EINTCONST) && canadd2(left, CInt64_Neg(right->data.intval)))
+ return left;
+
+ left = makediadicnode(left, right, ESUB);
+ if (IS_TYPE_FLOAT(left->rtype))
+ left = CExpr_BinaryFloatExpression(left);
+ return left;
+}
+
+ENode *checkreference(ENode *expr) {
+ if (!IS_TYPE_REFERENCE(expr->rtype))
+ return expr;
+
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TPTR_TARGET(expr->rtype);
+ return expr;
+}
+
+static ENode *pointer_generation2(ENode *expr) {
+ switch (expr->type) {
+ case EINDIRECT:
+ switch (expr->rtype->type) {
+ case TYPEARRAY:
+ switch (expr->data.monadic->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ expr->type = ETYPCON;
+ expr->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype));
+ return expr;
+ default:
+ expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype));
+ expr->data.monadic->flags = expr->flags;
+ return expr->data.monadic;
+ }
+ case TYPEFUNC:
+ expr = expr->data.monadic;
+ if (ENODE_IS(expr, EOBJREF) && expr->data.objref->datatype == DINLINEFUNC)
+ CError_Error(CErrorStr175);
+ return expr;
+ }
+ }
+ return expr;
+}
+
+ENode *pointer_generation(ENode *expr) {
+ return CExpr_RewriteConst(pointer_generation2(expr));
+}
+
+ENode *CExpr_PointerGeneration(ENode *expr) {
+ switch (expr->type) {
+ case EINDIRECT:
+ switch (expr->rtype->type) {
+ case TYPEARRAY:
+ expr->data.monadic->rtype = CDecl_NewPointerType(TPTR_TARGET(expr->rtype));
+ return expr->data.monadic;
+ case TYPEFUNC:
+ return expr->data.monadic;
+ }
+ }
+ return expr;
+}
+
+static void CExpr_ConstPointerCheck(ENode *expr, Type *type, short qual) {
+ Type *exprtype;
+ Type *b;
+ Type *a;
+ short exprqual;
+
+ exprtype = expr->rtype;
+ if (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_POINTER_ONLY(exprtype)) {
+ exprqual = expr->flags;
+
+ if (TPTR_TARGET(type) == &stvoid) {
+ exprqual = CParser_GetCVTypeQualifiers(TPTR_TARGET(exprtype), exprqual);
+ } else {
+ a = TPTR_TARGET(type);
+ b = TPTR_TARGET(exprtype);
+ while (IS_TYPE_POINTER_ONLY(a) && IS_TYPE_POINTER_ONLY(b)) {
+ if (CParser_IsMoreCVQualified(TPTR_QUAL(b), TPTR_QUAL(a))) {
+ CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, qual);
+ return;
+ }
+ a = TPTR_TARGET(a);
+ b = TPTR_TARGET(b);
+ }
+ }
+
+ if (CParser_IsMoreCVQualified(exprqual, qual)) {
+ CError_Warning(CErrorStr220, expr->rtype, ENODE_QUALS(expr), type, (UInt32) qual);
+ }
+ }
+}
+
+ENode *oldassignmentpromotion(ENode *expr, Type *type, short qual, Boolean flag) {
+ Boolean is_ref;
+ UInt32 ref_qual;
+ short orig_qual;
+
+ is_ref = 0;
+ if (!IS_TYPE_MEMBERPOINTER(type)) {
+ if (IS_TYPE_REFERENCE(type)) {
+ if (ENODE_IS(expr, ECOND))
+ expr = CExpr_LValue(expr, 0, 0);
+ expr = pointer_generation2(expr);
+ ref_qual = CParser_GetCVTypeQualifiers(expr->rtype, expr->flags);
+ is_ref = 1;
+ } else {
+ expr = pointer_generation(expr);
+ }
+ }
+
+ if (ENODE_IS(expr, EMEMBER))
+ expr = getpointertomemberfunc(expr, type, 1);
+
+ if (!is_ref)
+ CExpr_ConstPointerCheck(expr, type, qual);
+ else
+ CExpr_ConstPointerCheck(expr, TPTR_TARGET(type), qual);
+
+ if (!(assign_check(expr, type, orig_qual = qual, 1, 0, flag)))
+ return expr;
+
+ if (is_ref) {
+ if (temp_reference_init) {
+ switch (TPTR_TARGET(type)->type) {
+ case TYPEPOINTER:
+ qual = TPTR_QUAL(TPTR_TARGET(type));
+ }
+ if (!(qual & Q_CONST))
+ CError_Warning(CErrorStr228);
+ } else {
+ if (ref_qual && ref_qual > CParser_GetCVTypeQualifiers(TPTR_TARGET(type), orig_qual))
+ CError_Warning(CErrorStr259);
+ }
+ }
+
+ return assign_node;
+}
+
+ENode *argumentpromotion(ENode *expr, Type *type, short qual, Boolean flag) {
+ ENode *tmp;
+ ENodeList *list;
+
+ if (IS_TYPE_CLASS(type) && CClass_ReferenceArgument(TYPE_CLASS(type))) {
+ if ((tmp = CExpr_IsTempConstruction(expr, type, NULL)))
+ return tmp;
+
+ list = lalloc(sizeof(ENodeList));
+ list->next = NULL;
+ list->node = expr;
+ tmp = CExpr_ConstructObject(
+ TYPE_CLASS(type),
+ create_temp_node(type),
+ list, 1, 1, 1, 1, 0);
+ return getnodeaddress(tmp, 0);
+ }
+
+ return CExpr_AssignmentPromotion(expr, type, qual, flag);
+}
+
+ENode *classargument(ENode *expr) {
+ ENodeList *list;
+
+ if (CClass_CopyConstructor(TYPE_CLASS(expr->rtype))) {
+ list = lalloc(sizeof(ENodeList));
+ list->next = NULL;
+ list->node = expr;
+ return CExpr_ConstructObject(
+ TYPE_CLASS(expr->rtype),
+ create_temp_node(expr->rtype),
+ list, 1, 1, 1, 1, 0);
+ }
+
+ return expr;
+}
+
+ENodeList *CExpr_ScanExpressionList(Boolean is_parens) {
+ ENodeList *list;
+ ENodeList *current;
+
+ if (is_parens && tk == ')')
+ return NULL;
+
+ list = current = lalloc(sizeof(ENodeList));
+
+ while (1) {
+ current->next = NULL;
+ current->node = assignment_expression();
+ if (copts.old_argmatch && !ENODE_IS(current->node, EMEMBER))
+ current->node = pointer_generation(current->node);
+
+ if (is_parens) {
+ if (tk == ')')
+ break;
+ } else {
+ if (tk == ']')
+ break;
+ }
+
+ if (tk != ',') {
+ CError_ErrorSkip(CErrorStr116);
+ break;
+ }
+
+ tk = lex();
+ current->next = lalloc(sizeof(ENodeList));
+ current = current->next;
+ }
+
+ return list;
+}
+
+static ENode *skipcommaexpr(ENode *expr) {
+ while (ENODE_IS(expr, ECOMMA))
+ expr = expr->data.diadic.right;
+ return expr;
+}
+
+ENode *CExpr_DoExplicitConversion(Type *type, UInt32 qual, ENodeList *list) {
+ Object *obj;
+ ENode *tmp;
+
+ if (!IS_TYPE_CLASS(type)) {
+ if (!list)
+ return do_typecast(nullnode(), type, qual);
+ if (list->next)
+ CError_Error(CErrorStr356);
+ return do_typecast(pointer_generation(list->node), type, qual);
+ }
+
+ CDecl_CompleteType(type);
+ if (!(TYPE_CLASS(type)->flags & CLASS_FLAGS_2))
+ CError_Error(CErrorStr136, type, 0);
+
+ CanCreateObject(type);
+ if (!list && CClass_IsPODClass(TYPE_CLASS(type))) {
+ obj = CParser_NewGlobalDataObject(NULL);
+ obj->name = CParser_GetUniqueName();
+ obj->nspace = cscope_root;
+ obj->type = type;
+ obj->qual = qual;
+ obj->sclass = TK_STATIC;
+ CInit_DeclareData(obj, NULL, NULL, type->size);
+
+ tmp = makemonadicnode(create_temp_node(type), EINDIRECT);
+ tmp->rtype = type;
+ tmp->flags = qual & ENODE_FLAG_QUALS;
+ return makediadicnode(tmp, create_objectnode(obj), EASS);
+ }
+
+ return CExpr_ConstructObject(TYPE_CLASS(type), create_temp_node(type), list, 1, 1, 1, 1, 1);
+}
+
+static ENode *CExpr_TemplArgDepCast(Type *type, UInt32 qual, ENodeList *args) {
+ ENode *expr = CExpr_NewTemplDepENode(TDE_CAST);
+ expr->data.templdep.u.cast.args = args;
+ expr->data.templdep.u.cast.type = type;
+ expr->data.templdep.u.cast.qual = qual;
+ return expr;
+}
+
+static ENode *CExpr_ParseExplicitConversion(Type *type, UInt32 qual) {
+ ENodeList *args;
+ ENodeList *scan;
+
+ if (IS_TEMPL_CLASS(type) && !CParser_CheckTemplateClassUsage(TEMPL_CLASS(type), 1))
+ type = TYPE(&stsignedint);
+
+ if (tk == '(')
+ tk = lex();
+ else
+ CError_Error(114);
+
+ args = CExpr_ScanExpressionList(1);
+ if (tk != ')') {
+ CError_Error(115);
+ return nullnode();
+ }
+
+ tk = lex();
+ if (CTemplTool_IsTemplateArgumentDependentType(type))
+ return CExpr_TemplArgDepCast(type, qual, args);
+
+ for (scan = args; scan; scan = scan->next) {
+ if (CTemplTool_IsTemplateArgumentDependentExpression(scan->node))
+ return CExpr_TemplArgDepCast(type, qual, args);
+ }
+
+ return CExpr_DoExplicitConversion(type, qual, args);
+}
+
+static ENode *CExpr_MemberVarAccess(BClassList *path, ObjMemberVar *var, ENode *expr) {
+ ENode *accessnode;
+ BClassList *varpath;
+
+#line 1152
+ CError_ASSERT(path);
+
+ if (TYPE_CLASS(path->type)->sominfo)
+ return CSOM_MemberVarAccess(path, var, expr);
+
+ varpath = NULL;
+ if (var->has_path)
+ varpath = OBJ_MEMBER_VAR_PATH(var)->path;
+ accessnode = CExpr_GetClassAccessNode(path, varpath, expr, NULL, var->access, 1);
+ if (!accessnode)
+ return nullnode();
+
+ return CClass_AccessMember(accessnode, var->type, var->qual, var->offset);
+}
+
+static Boolean CExpr_IsTemplateFunc(Object *obj) {
+ return IS_TEMPL_FUNC(obj->type);
+}
+
+static ENode *CExpr_ExplicitTemplateArgCheck(CScopeParseResult *pr) {
+ NameSpaceObjectList *list;
+ NameSpaceObjectList *newhead;
+ NameSpaceObjectList *newlist;
+ ENode *expr;
+
+ if (pr->obj_10) {
+ if (pr->obj_10->otype != OT_OBJECT || !CExpr_IsTemplateFunc(OBJECT(pr->obj_10)))
+ return NULL;
+
+ list = lalloc(sizeof(NameSpaceObjectList));
+ memclrw(list, sizeof(NameSpaceObjectList));
+ list->object = pr->obj_10;
+ } else if (pr->nsol_14) {
+ for (list = pr->nsol_14; list; list = list->next) {
+ if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) {
+ newhead = newlist = galloc(sizeof(NameSpaceObjectList));
+ *newlist = *list;
+ newlist->next = NULL;
+ while ((list = list->next)) {
+ if (list->object->otype == OT_OBJECT && CExpr_IsTemplateFunc(OBJECT(list->object))) {
+ newlist->next = galloc(sizeof(NameSpaceObjectList));
+ newlist = newlist->next;
+ *newlist = *list;
+ newlist->next = NULL;
+ }
+ }
+ list = newhead;
+ break;
+ }
+ }
+ if (!list)
+ return NULL;
+ } else {
+ return NULL;
+ }
+
+ expr = CExpr_NewENode(EOBJLIST);
+ expr->rtype = OBJECT(list->object)->type;
+ expr->data.objlist.list = list;
+ expr->data.objlist.templargs = CTempl_ParseUncheckTemplArgs(NULL, 0);
+
+ tk = lex();
+ return expr;
+}
+
+ENode *CExpr_MakeNameLookupResultExpr(CScopeParseResult *pr) {
+ ENode *expr;
+
+ if (pr->obj_10) {
+ switch (pr->obj_10->otype) {
+ case OT_OBJECT:
+ CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10));
+ return create_objectnode(OBJECT(pr->obj_10));
+ case OT_ENUMCONST:
+ CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10));
+ expr = lalloc(sizeof(ENode));
+ expr->type = EINTCONST;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = OBJ_ENUM_CONST(pr->obj_10)->type;
+ expr->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val;
+ return expr;
+ case OT_MEMBERVAR:
+ CError_Error(0xDD);
+ return nullnode();
+ default:
+#line 1268
+ CError_FATAL();
+ }
+ }
+
+ if (pr->nsol_14) {
+ expr = CExpr_NewENode(EOBJLIST);
+ expr->rtype = OBJECT(pr->nsol_14->object)->type;
+ expr->data.objlist.list = pr->nsol_14;
+ return expr;
+ }
+
+#line 1278
+ CError_FATAL();
+ return NULL;
+}
+
+static Type *CExpr_NewPTMType(EMemberInfo *member, Object *obj) {
+ TypeMemberPointer *ptm;
+ TypeMethod *tmethod;
+ BClassList *path;
+
+ ptm = galloc(sizeof(TypeMemberPointer));
+ memclrw(ptm, sizeof(TypeMemberPointer));
+ ptm->type = TYPEMEMBERPOINTER;
+
+ if (member->list->object->otype == OT_MEMBERVAR) {
+ path = member->path;
+ while (path->next)
+ path = path->next;
+ ptm->size = 4;
+ ptm->ty2 = path->type;
+ ptm->ty1 = OBJ_MEMBER_VAR(member->list->object)->type;
+ } else {
+ if (!obj) {
+#line 1306
+ CError_ASSERT(member->list->object->otype == OT_OBJECT);
+ obj = OBJECT(member->list->object);
+#line 1308
+ CError_ASSERT(IS_TYPE_FUNC(obj->type));
+ }
+
+ tmethod = galloc(sizeof(TypeMethod));
+ memclrw(tmethod, sizeof(TypeMethod));
+ *tmethod = *TYPE_METHOD(obj->type);
+
+#line 1312
+ CError_ASSERT(tmethod->args);
+
+ tmethod->args = tmethod->args->next;
+ CDecl_MakePTMFuncType(TYPE_FUNC(tmethod));
+ tmethod->flags &= ~FUNC_FLAGS_2;
+
+ ptm->size = 12;
+ ptm->ty2 = TYPE(tmethod->theclass);
+ ptm->ty1 = TYPE(tmethod);
+ }
+
+ return TYPE(ptm);
+}
+
+static ENode *CExpr_ParseNameResultExpr(CScopeParseResult *pr, ENode *expr, Boolean flag1, Boolean flag2) {
+ ENode *result;
+ ENode *ta_expr;
+ ObjEnumConst *oec;
+ TemplateAction *act;
+ EMemberInfo *member;
+ NameSpaceObjectList *list;
+ Object *obj;
+ TypeFunc *tfunc;
+ SInt32 val;
+
+ if (pr->x8) {
+ if (copts.cplusplus) {
+ if (IS_TYPE_TEMPLATE(pr->x8)) {
+ if (TYPE_TEMPLATE(pr->x8)->dtype == TEMPLDEP_ARGUMENT && TYPE_TEMPLATE(pr->x8)->u.pid.type == TPT_NONTYPE) {
+ result = CExpr_NewTemplDepENode(TDE_PARAM);
+ result->data.templdep.u.pid = TYPE_TEMPLATE(pr->x8)->u.pid;
+ tk = lex();
+ return result;
+ }
+ if (TYPE_TEMPLATE(pr->x8)->dtype == TEMPLDEP_QUALNAME && !pr->x20) {
+ result = CExpr_NewTemplDepENode(TDE_QUALNAME);
+ result->data.templdep.u.qual.type = TYPE_TEMPLATE(pr->x8)->u.qual.type;
+ result->data.templdep.u.qual.name = TYPE_TEMPLATE(pr->x8)->u.qual.name;
+ tk = lex();
+ return result;
+ }
+ }
+ tk = lex();
+ return CExpr_ParseExplicitConversion(pr->x8, pr->xC);
+ }
+ CError_ErrorSkip(CErrorStr141);
+ tk = lex();
+ return nullnode();
+ }
+
+ if (pr->obj_10) {
+ switch (pr->obj_10->otype) {
+ case OT_OBJECT:
+ if (OBJECT(pr->obj_10)->nspace && OBJECT(pr->obj_10)->nspace->theclass && (OBJECT(pr->obj_10)->nspace->theclass->flags & CLASS_FLAGS_100)) {
+ result = CExpr_NewTemplDepENode(TDE_QUALTEMPL); // not sure this is right tbh
+ result->data.templdep.u.obj = OBJECT(pr->obj_10);
+ tk = lex();
+ return result;
+ }
+ if (!expr || !IS_TEMPL_FUNC(OBJECT(pr->obj_10)->type)) {
+ if (!IS_TYPE_NONSTATIC_METHOD(OBJECT(pr->obj_10)->type)) {
+ tk = lex();
+ if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr)))
+ return ta_expr;
+ if (OBJECT(pr->obj_10)->datatype == DLOCAL && OBJECT(pr->obj_10)->u.var.info->func != cscope_currentfunc) {
+ CError_Error(CErrorStr330);
+ return nullnode();
+ }
+ if (OBJECT(pr->obj_10)->datatype == DEXPR) {
+ result = CInline_CopyExpression(OBJECT(pr->obj_10)->u.expr, CopyMode0);
+ if (IS_TYPE_POINTER_ONLY(result->rtype) && ENODE_IS(result, EINTCONST)) {
+ result = makemonadicnode(result, ETYPCON);
+ result->data.monadic->rtype = TYPE(&stunsignedlong);
+ }
+ return result;
+ }
+ CClass_CheckObjectAccess(pr->bcl_18, OBJECT(pr->obj_10));
+ if (tk == '(' && flag2 && OBJECT(pr->obj_10)->datatype == DFUNC && copts.cplusplus && !pr->x1D && !IS_TYPEFUNC_METHOD(TYPE_FUNC(OBJECT(pr->obj_10)->type))) {
+ result = CExpr_NewENode(EOBJLIST);
+ result->rtype = OBJECT(pr->obj_10)->type;
+ result->data.objlist.list = galloc(sizeof(NameSpaceObjectList));
+ result->data.objlist.list->next = pr->nsol_14;
+ result->data.objlist.list->object = pr->obj_10;
+ result->data.objlist.name = OBJECT(pr->obj_10)->name;
+ return result;
+ }
+
+ result = create_objectnode(OBJECT(pr->obj_10));
+ if (expr) {
+ while (ENODE_IS(expr, EINDIRECT))
+ expr = expr->data.monadic;
+ switch (expr->type) {
+ case EINTCONST:
+ case EOBJREF:
+ case EOBJLIST:
+ break;
+ default:
+ result = makecommaexpression(expr, result);
+ }
+ }
+ return result;
+ }
+ if (CClass_IsDestructor(OBJECT(pr->obj_10))) {
+ if ((tk = lex()) != '(') {
+ CError_Error(114);
+ return nullnode();
+ }
+ if ((tk = lex()) != ')') {
+ CError_Error(115);
+ return nullnode();
+ }
+ if (!expr && (!cscope_currentfunc || !cscope_currentclass || !cscope_is_member_func)) {
+ CError_Error(221);
+ return nullnode();
+ }
+ if (pr->isambig)
+ CError_Error(188);
+
+ if ((expr = CExpr_GetClassAccessNode(pr->bcl_18, NULL, expr, OBJECT(pr->obj_10), pr->obj_10->access, 1))) {
+ tk = lex();
+ return CABI_DestroyObject(OBJECT(pr->obj_10), expr->data.monadic, 1, pr->x1D, 0);
+ }
+ }
+ }
+ break;
+ case OT_ENUMCONST:
+ CClass_CheckEnumAccess(pr->bcl_18, OBJ_ENUM_CONST(pr->obj_10));
+ oec = OBJ_ENUM_CONST(pr->obj_10);
+ if (CInt64_IsZero(&oec->val) && IS_TYPE_ENUM(oec->type) && TYPE_ENUM(oec->type)->nspace && TYPE_ENUM(oec->type)->nspace->theclass && (TYPE_ENUM(oec->type)->nspace->theclass->flags & CLASS_FLAGS_100)) {
+ val = 0;
+ expr = NULL;
+ for (act = TEMPL_CLASS(TYPE_ENUM(oec->type)->nspace->theclass)->actions; act; act = act->next) {
+ if (act->type == TAT_ENUMERATOR) {
+ if (act->u.enumerator.initexpr) {
+ expr = act->u.enumerator.initexpr;
+ val = 0;
+ } else {
+ val++;
+ }
+ if (act->u.enumerator.objenumconst == oec) {
+#line 1521
+ CError_ASSERT(expr);
+ expr = CInline_CopyExpression(expr, CopyMode0);
+ if (val)
+ expr = makediadicnode(expr, intconstnode(TYPE(&stsignedlong), val), EADD);
+ tk = lex();
+ return expr;
+ }
+ }
+ }
+ }
+ result = lalloc(sizeof(ENode));
+ result->type = EINTCONST;
+ result->cost = 0;
+ result->flags = 0;
+ result->rtype = OBJ_ENUM_CONST(pr->obj_10)->type;
+ result->data.intval = OBJ_ENUM_CONST(pr->obj_10)->val;
+ tk = lex();
+ return result;
+ case OT_MEMBERVAR:
+ if (!flag1 || expr || !pr->x1D) {
+ if (pr->isambig)
+ CError_Error(188);
+ result = checkreference(CExpr_MemberVarAccess(pr->bcl_18, OBJ_MEMBER_VAR(pr->obj_10), expr));
+ tk = lex();
+ return result;
+ }
+ break;
+ default:
+#line 1552
+ CError_FATAL();
+ }
+
+ member = lalloc(sizeof(EMemberInfo));
+ memclrw(member, sizeof(EMemberInfo));
+ member->path = pr->bcl_18;
+ member->expr = expr;
+ member->pr_1D = pr->x1D;
+ member->isambig = pr->isambig;
+ if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) {
+#line 1564
+ CError_ASSERT(ENODE_IS(ta_expr, EOBJLIST));
+ member->list = ta_expr->data.objlist.list;
+ member->templargs = ta_expr->data.objlist.templargs;
+ } else {
+ member->list = galloc(sizeof(NameSpaceObjectList));
+ member->list->next = NULL;
+ member->list->object = pr->obj_10;
+ }
+
+ result = CExpr_NewENode(EMEMBER);
+ result->data.emember = member;
+ result->rtype = &stvoid;
+ return result;
+ }
+
+ if (pr->nsol_14) {
+ if ((tk = lex()) == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr))) {
+#line 1591
+ CError_ASSERT(ENODE_IS(ta_expr, EOBJLIST));
+ for (list = ta_expr->data.objlist.list; list; list = list->next) {
+ if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) {
+ member = lalloc(sizeof(EMemberInfo));
+ memclrw(member, sizeof(EMemberInfo));
+
+ member->path = pr->bcl_18;
+ member->expr = expr;
+ member->list = ta_expr->data.objlist.list;
+ member->templargs = ta_expr->data.objlist.templargs;
+ member->pr_1D = pr->x1D;
+ member->isambig = pr->isambig;
+
+ result = CExpr_NewENode(EMEMBER);
+ result->data.emember = member;
+ result->rtype = &stvoid;
+ return result;
+ }
+ }
+ return ta_expr;
+ }
+
+ for (list = pr->nsol_14; list; list = list->next) {
+ if (list->object->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(OBJECT(list->object)->type)) {
+ member = lalloc(sizeof(EMemberInfo));
+ memclrw(member, sizeof(EMemberInfo));
+
+ member->path = pr->bcl_18;
+ member->expr = expr;
+ member->list = pr->nsol_14;
+ member->pr_1D = pr->x1D;
+ member->isambig = pr->isambig;
+
+ result = CExpr_NewENode(EMEMBER);
+ result->data.emember = member;
+ result->rtype = &stvoid;
+ return result;
+ }
+ }
+
+ if (tk == '<' && (ta_expr = CExpr_ExplicitTemplateArgCheck(pr)))
+ return ta_expr;
+
+ result = CExpr_NewENode(EOBJLIST);
+ result->rtype = OBJECT(pr->nsol_14->object)->type;
+ result->data.objlist.list = pr->nsol_14;
+ if (tk == '(' && copts.cplusplus && flag2 && !pr->x1D && pr->nsol_14->object->otype == OT_OBJECT)
+ result->data.objlist.name = OBJECT(pr->nsol_14->object)->name;
+ return result;
+ }
+
+ if (pr->name_4) {
+ if (copts.cplusplus && flag2) {
+ if (lookahead() == '(') {
+ result = CExpr_NewENode(EOBJLIST);
+ result->rtype = &stvoid;
+ result->data.objlist.name = pr->name_4;
+ tk = lex();
+ return result;
+ }
+ CError_Error(CErrorStr140, pr->name_4->name);
+ tk = lex();
+ return nullnode();
+ }
+
+ if (lookahead() != '(') {
+ CError_Error(CErrorStr140, pr->name_4->name);
+ tk = lex();
+ return nullnode();
+ }
+
+ if (copts.require_prototypes)
+ CError_Error(178);
+
+ tfunc = galloc(sizeof(TypeFunc));
+ memclrw(tfunc, sizeof(TypeFunc));
+ tfunc->type = TYPEFUNC;
+ tfunc->functype = TYPE(&stsignedint);
+ tfunc->args = &oldstyle;
+ CDecl_SetFuncFlags(tfunc, 0);
+
+ obj = CParser_NewFunctionObject(NULL);
+ obj->name = pr->name_4;
+ obj->sclass = TK_EXTERN;
+ obj->nspace = cscope_root;
+ obj->type = TYPE(tfunc);
+
+ CScope_AddGlobalObject(obj);
+ tk = lex();
+ return create_objectrefnode(obj);
+ }
+
+#line 1711
+ CError_FATAL();
+ return NULL;
+}
+
+static ENode *CExpr_ParseRotate(Boolean is_right) {
+ ENode *expr1;
+ ENode *expr2;
+
+ if (lex() != '(') {
+ CError_Error(114);
+ return nullnode();
+ }
+
+ tk = lex();
+ expr1 = assignment_expression();
+
+ if (tk != ',') {
+ CError_Error(116);
+ return nullnode();
+ }
+
+ tk = lex();
+ expr2 = assignment_expression();
+
+ if (tk != ')') {
+ CError_Error(115);
+ return nullnode();
+ }
+
+ if (!IS_TYPE_INT(expr1->rtype))
+ expr1 = forceintegral(expr1);
+ expr2 = integralpromote(expr2);
+
+ tk = lex();
+ if (iszero(expr1) || iszero(expr2))
+ return expr1;
+
+ return makediadicnode(expr1, expr2, is_right ? EROTR : EROTL);
+}
+
+static ENode *CExpr_ParseNextArg(void) {
+ NameSpaceObjectList *list;
+ CScopeParseResult pr;
+ ENode *expr;
+ SInt32 rounded_size;
+
+ if ((tk = lex()) != '(') {
+ CError_Error(114);
+ return nullnode();
+ }
+ if ((tk = lex()) != TK_IDENTIFIER) {
+ CError_Error(0x6B);
+ return nullnode();
+ }
+
+ list = CScope_FindObjectList(&pr, tkidentifier);
+ if (!list) {
+ CError_Error(140, tkidentifier->name);
+ return nullnode();
+ }
+
+ if (list->object->otype != OT_OBJECT || OBJECT(list->object)->datatype != DLOCAL) {
+ CError_Error(140, tkidentifier->name);
+ return nullnode();
+ }
+
+ rounded_size = CMach_RoundedSizeOf(OBJECT(list->object));
+ expr = CExpr_MakeObjRefNode(OBJECT(list->object), 1);
+ expr = makediadicnode(expr, intconstnode(CABI_GetPtrDiffTType(), rounded_size), EADD);
+ expr->rtype = TYPE(&void_ptr);
+
+ if ((tk = lex()) != ')') {
+ CError_Error(115);
+ return expr;
+ } else {
+ tk = lex();
+ return expr;
+ }
+}
+
+static ENode *CExpr_ParseVecStep(void) {
+ ENode *expr;
+ Type *type;
+ SInt32 value;
+ DeclInfo di;
+
+ expr = intconstnode(TYPE(&stsignedint), 0);
+ if ((tk = lex()) == '(') {
+ if (tk == '(' && islookaheaddeclaration()) {
+ tk = lex();
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 0);
+ scandeclarator(&di);
+ if (di.name)
+ CError_Error(121);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ type = di.thetype;
+ if (IS_TYPE_REFERENCE(type))
+ type = TPTR_TARGET(type);
+ } else {
+ expr = unary_expression();
+ if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD))
+ CError_Error(144);
+ type = expr->rtype;
+ }
+
+ CDecl_CompleteType(type);
+ if (IS_TYPE_VECTOR(type)) {
+ switch (TYPE_STRUCT(type)->stype) {
+ case STRUCT_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ value = 16;
+ break;
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_E:
+ value = 8;
+ break;
+ default:
+ value = 4;
+ }
+ expr = intconstnode(TYPE(&stsignedint), value);
+ } else {
+ PPCError_Error(104, "vec_step", "vec_step", type, 0);
+ }
+ } else {
+ CError_Error(114);
+ }
+
+ return expr;
+}
+
+static SInt32 CExpr_BuiltInComputeAlign(Type *type) {
+ return CMach_GetTypeAlign(type);
+}
+
+static SInt32 CExpr_AtomTypeID(IntegralType what) {
+ switch (what) {
+ case IT_BOOL: return 1;
+ case IT_CHAR: return 2;
+ case IT_SCHAR: return 3;
+ case IT_UCHAR: return 4;
+ case IT_WCHAR_T: return 5;
+ case IT_SHORT: return 6;
+ case IT_USHORT: return 7;
+ case IT_INT: return 8;
+ case IT_UINT: return 9;
+ case IT_LONG: return 10;
+ case IT_ULONG: return 10;
+ case IT_LONGLONG: return 12;
+ case IT_ULONGLONG: return 13;
+ case IT_FLOAT: return 14;
+ case IT_SHORTDOUBLE: return 15;
+ case IT_DOUBLE: return 16;
+ case IT_LONGDOUBLE: return 17;
+ case IT_17: return 32;
+ case IT_18: return 33;
+ case IT_19: return 34;
+ case IT_20: return 35;
+ case IT_21: return 36;
+ case IT_22: return 37;
+ case IT_23: return 38;
+ case IT_24: return 39;
+ default:
+#line 1976
+ CError_FATAL();
+ return 0;
+ }
+}
+
+static SInt32 CExpr_BuiltInComputeType(Type *type) {
+ switch (type->type) {
+ case TYPEINT:
+ return 0x100 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral);
+ case TYPEFLOAT:
+ return 0x200 | CExpr_AtomTypeID(TYPE_INTEGRAL(type)->integral);
+ case TYPEENUM:
+ return 0x400 | (CExpr_BuiltInComputeType(TYPE_ENUM(type)->enumtype) & 0xFF);
+ case TYPEPOINTER:
+ return 0x800;
+ case TYPEARRAY:
+ return 0x1000;
+ case TYPESTRUCT:
+ return 0x2000;
+ case TYPECLASS:
+ return 0x2000;
+ case TYPEMEMBERPOINTER:
+ return 0x4000;
+ case TYPEFUNC:
+ return 0x8000;
+ default:
+ CError_Error(146);
+ case TYPEVOID:
+ return 0;
+ }
+}
+
+static SInt32 CExpr_BuiltInClassifyType(Type *type) {
+ switch (type->type) {
+ case TYPEVOID: return 0;
+ case TYPEFUNC: return 10;
+ case TYPEENUM: return 3;
+ case TYPEINT: return 1;
+ case TYPEFLOAT: return 8;
+ case TYPEPOINTER: case TYPEMEMBERPOINTER: return 5;
+ case TYPEARRAY: return 14;
+ case TYPESTRUCT: return 12;
+ case TYPECLASS: return 12;
+ case TYPEBITFIELD: return -1;
+ case TYPETEMPLATE: return -1;
+ default: return -1;
+ }
+}
+
+static SInt32 CExpr_BuiltInComputeVArgType(Type *type) {
+ switch (type->type) {
+ case TYPEINT:
+ case TYPEENUM:
+ return 0;
+ case TYPEFLOAT:
+ return 1;
+ default:
+ return 2;
+ }
+}
+
+static Type *CExpr_ParseTypeExpression(Boolean *outflag) {
+ ENode *expr;
+ Type *type;
+ DeclInfo di;
+
+ tk = lex();
+ if (tk == '(' && islookaheaddeclaration()) {
+ tk = lex();
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 0);
+ scandeclarator(&di);
+ if (di.name)
+ CError_Error(121);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ type = di.thetype;
+ if (IS_TYPE_REFERENCE(type))
+ type = TPTR_TARGET(type);
+ } else {
+ expr = unary_expression();
+ if (ENODE_IS(expr, EINDIRECT) && ENODE_IS(expr->data.monadic, EBITFIELD))
+ CError_Error(144);
+
+ if (outflag)
+ *outflag = ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval);
+
+ type = expr->rtype;
+ }
+
+ CDecl_CompleteType(type);
+ return type;
+}
+
+static ENode *CExpr_ParseBuiltin(SInt32 (*parser)(Type *)) {
+ ENode *expr;
+ expr = intconstnode(TYPE(&stsignedint), 0);
+ CInt64_SetLong(&expr->data.intval, parser(CExpr_ParseTypeExpression(NULL)));
+ return expr;
+}
+
+static ENode *CExpr_ParseBuiltin_isintconst(void) {
+ ENode *expr;
+ expr = intconstnode(TYPE(&stsignedint), 0);
+
+ tk = lex();
+ if (tk != '(')
+ CError_ErrorSkip(121);
+ else
+ tk = lex();
+
+ if (ENODE_IS(expression(), EINTCONST))
+ CInt64_SetLong(&expr->data.intval, 1);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ return expr;
+}
+
+static ENode *primary_expression(Boolean flag) {
+ CScopeParseResult pr;
+ ENode *expr;
+
+ switch (tk) {
+ case TK_TRUE:
+ expr = lalloc(sizeof(ENode));
+ expr->type = EINTCONST;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = TYPE(&stbool);
+ CInt64_SetULong(&expr->data.intval, 1);
+ tk = lex();
+ return expr;
+ case TK_FALSE:
+ expr = lalloc(sizeof(ENode));
+ expr->type = EINTCONST;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = TYPE(&stbool);
+ CInt64_SetULong(&expr->data.intval, 0);
+ tk = lex();
+ return expr;
+ case TK_INTCONST:
+ expr = lalloc(sizeof(ENode));
+ expr->type = EINTCONST;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = atomtype();
+ expr->data.intval = tkintconst;
+ tk = lex();
+ return expr;
+ case TK_FLOATCONST:
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFLOATCONST;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = atomtype();
+ expr->data.floatval = tkfloatconst;
+ tk = lex();
+ return expr;
+ case TK_STRING:
+ expr = CExpr_NewENode(ESTRINGCONST);
+ expr->rtype = CDecl_NewArrayType(ispascalstring ? TYPE(&stunsignedchar) : TYPE(&stchar), tksize);
+ expr->data.string.size = tksize;
+ expr->data.string.data = tkstring;
+ expr->data.string.ispascal = ispascalstring;
+ if (copts.const_strings)
+ expr->flags = ENODE_FLAG_CONST;
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype);
+ tk = lex();
+ return expr;
+ case TK_STRING_WIDE:
+ expr = CExpr_NewENode(ESTRINGCONST);
+ expr->rtype = CDecl_NewArrayType(CParser_GetWCharType(), tksize);
+ expr->data.string.size = tksize;
+ expr->data.string.data = tkstring;
+ expr->data.string.ispascal = ispascalstring;
+ if (copts.const_strings)
+ expr->flags = ENODE_FLAG_CONST;
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->data.monadic->rtype = CDecl_NewPointerType(expr->rtype);
+ tk = lex();
+ return expr;
+ case TK_THIS:
+ case TK_SELF:
+ expr = CClass_CreateThisSelfExpr();
+ if (!expr)
+ expr = nullnode();
+ tk = lex();
+ return expr;
+ case TK_AT_SELECTOR:
+ return CObjC_ParseSelectorExpression();
+ case TK_AT_ENCODE:
+ return CObjC_ParseEncodeExpression();
+ case TK_AT_PROTOCOL:
+ return CObjC_ParseProtocolExpression();
+ case '@':
+ if (copts.objective_c)
+ return CObjC_ParseAtExpression();
+ break;
+ case '(':
+ tk = lex();
+ expr = s_expression();
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+ if (ENODE_IS(expr, EASS))
+ expr->flags |= ENODE_FLAG_80;
+ return expr;
+ case '[':
+ if (copts.objective_c)
+ return CObjC_ParseMessageExpression();
+ break;
+ case TK_IDENTIFIER:
+ if (tkidentifier->name[0] == '_' && tkidentifier->name[1] == '_') {
+ if (!strcmp(tkidentifier->name, "__builtin_align"))
+ return CExpr_ParseBuiltin(CExpr_BuiltInComputeAlign);
+ if (!strcmp(tkidentifier->name, "__builtin_ntype"))
+ return CExpr_ParseBuiltin(CExpr_BuiltInComputeType);
+ if (!strcmp(tkidentifier->name, "__builtin_type") || !strcmp(tkidentifier->name, "__builtin_vargtype"))
+ return CExpr_ParseBuiltin(CExpr_BuiltInComputeVArgType);
+ if (!strcmp(tkidentifier->name, "__builtin_classify_type"))
+ return CExpr_ParseBuiltin(CExpr_BuiltInClassifyType);
+ if (!strcmp(tkidentifier->name, "__builtin_next_arg"))
+ return CExpr_ParseNextArg();
+ }
+ if (copts.altivec_model && !strcmp("vec_step", tkidentifier->name))
+ return CExpr_ParseVecStep();
+ case '~':
+ case TK_OPERATOR:
+ case TK_INHERITED:
+ case TK_COLON_COLON:
+ if (CScope_ParseExprName(&pr))
+ return CExpr_ParseNameResultExpr(&pr, NULL, flag, 1);
+ tk = lex();
+ return nullnode();
+ }
+
+ CError_ErrorSkip(141);
+ return nullnode();
+}
+
+static ENode *CExpr_SimpleExplicitConversion(void) {
+ DeclInfo di;
+
+ memclrw(&di, sizeof(DeclInfo));
+
+ if (!copts.cpp_extensions && tk != TK_UU_TYPEOF_UU && tk != TK_TYPENAME && lookahead() != '(')
+ CError_Error(114);
+
+ CParser_GetDeclSpecs(&di, 0);
+ return CExpr_ParseExplicitConversion(di.thetype, di.qual);
+}
+
+static ENode *CExpr_NewPTMFCall(void) {
+ tk = lex();
+ CExpr_ScanExpressionList(1);
+
+ if (tk != ')') {
+ CError_Error(115);
+ return nullnode();
+ } else {
+#line 2465
+ CError_FATAL();
+ return nullnode();
+ }
+}
+
+static ENode *call_ptmf(ENode *expr) {
+ Type *rettype;
+ ENodeList *args;
+ ENodeList *list1;
+ ENodeList *list2;
+ Object *callobj;
+
+ rettype = TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype))->functype;
+ tk = lex();
+ args = CExpr_ScanExpressionList(1);
+
+ if (tk != ')') {
+ CError_Error(115);
+ return nullnode();
+ }
+
+ if (IS_TYPE_STRUCT(rettype) || IS_TYPE_CLASS(rettype) || IS_TYPE_12BYTES_MEMBERPOINTER(rettype))
+ callobj = rt_ptmf_scall4;
+ else
+ callobj = rt_ptmf_scall;
+
+ list1 = lalloc(sizeof(ENodeList));
+ list1->next = args;
+ list1->node = expr->data.mfpointer.accessnode->data.monadic;
+
+ list2 = lalloc(sizeof(ENodeList));
+ list2->next = list1;
+ list2->node = expr->data.mfpointer.mfpointer->data.monadic;
+
+ if (!copts.old_argmatch) {
+#line 2568
+ CError_ASSERT(IS_TYPE_POINTER_ONLY(list2->node->rtype));
+ list2->node->rtype = TYPE(&void_ptr);
+ }
+
+ expr = CExpr_GenericPtmfCall(
+ callobj,
+ TYPE_FUNC(TPTR_TARGET(expr->data.mfpointer.mfpointer->rtype)),
+ list2);
+ tk = lex();
+ return expr;
+}
+
+static ENode *CExpr_DummyDestr(ENode *expr) {
+ SInt32 state;
+ CScopeParseResult pr;
+ DeclInfo di;
+ NameSpace *nspace;
+
+ CPrep_TokenStreamGetState(&state);
+ nspace = cscope_current;
+ if ((tk = lex()) == TK_COLON_COLON) {
+ nspace = cscope_root;
+ tk = lex();
+ } else if (tk != '~' && tk != TK_IDENTIFIER && !(tk >= TK_AUTO && tk <= TK_BYREF)) {
+ CPrep_TokenStreamSetCurState(&state);
+ return NULL;
+ }
+
+loop:
+ if (tk == '~')
+ goto is_tilde;
+ if (tk == TK_IDENTIFIER) {
+ if (CScope_FindTypeName(nspace, tkidentifier, &pr)) {
+ tk = lex();
+ if (pr.nspace_0) {
+ if (tk == TK_COLON_COLON) {
+ tk = lex();
+ nspace = pr.nspace_0;
+ goto loop;
+ }
+ } else if (IS_TYPE_CLASS(pr.x8) && tk == TK_COLON_COLON) {
+ tk = lex();
+ nspace = TYPE_CLASS(pr.x8)->nspace;
+ goto loop;
+ } else {
+ if (!is_typesame(pr.x8, expr->rtype))
+ CError_Error(146);
+ if (tk == TK_COLON_COLON && ((tk = lex()) == '~') && ((tk = lex()) == TK_IDENTIFIER)) {
+ parse_dtor:
+ if (CScope_FindTypeName(nspace, tkidentifier, &pr) && !pr.nspace_0) {
+ if (!is_typesame(pr.x8, expr->rtype))
+ CError_Error(146);
+ tk = lex();
+ goto parsed;
+ }
+ }
+ }
+ }
+ } else if (tk >= TK_AUTO && tk <= TK_BYREF) {
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 0);
+ if (di.storageclass || di.qual || !is_typesame(di.thetype, expr->rtype))
+ CError_Error(146);
+ if (tk == TK_COLON_COLON && ((tk = lex()) == '~')) {
+ is_tilde:
+ if ((tk = lex()) == TK_IDENTIFIER)
+ goto parse_dtor;
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 0);
+ if (di.storageclass || !is_typesame(di.thetype, expr->rtype))
+ CError_Error(146);
+ goto parsed;
+ }
+ }
+
+ CError_Error(141);
+ return NULL;
+
+parsed:
+ if (tk == '(') {
+ if ((tk = lex()) != ')')
+ CError_Error(115);
+ else
+ tk = lex();
+ } else {
+ CError_Error(114);
+ }
+
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = &stvoid;
+ return expr;
+}
+
+static ENode *postfix_expression(Boolean flag) {
+ CScopeParseResult pr;
+ Conversion conv;
+ ENode *expr;
+ ENode *subexpr;
+ ENode *funcexpr;
+ ENodeList *args;
+ ENode *copy;
+ ENode *tmp;
+ StructMember *member;
+
+ if (copts.cplusplus) {
+ switch (tk) {
+ case TK_VOID:
+ case TK_CHAR:
+ case TK_SHORT:
+ case TK_INT:
+ case TK_LONG:
+ case TK_FLOAT:
+ case TK_DOUBLE:
+ case TK_SIGNED:
+ case TK_UNSIGNED:
+ case TK_UNK_113:
+ case TK_UNK_114:
+ case TK_UNK_115:
+ case TK_UNK_116:
+ case TK_UNK_117:
+ case TK_UNK_118:
+ case TK_UNK_119:
+ case TK_UNK_11A:
+ case TK_UU_TYPEOF_UU:
+ case TK_BOOL:
+ case TK_WCHAR_T:
+ case TK_TYPENAME:
+ expr = CExpr_SimpleExplicitConversion();
+ break;
+ default:
+ expr = primary_expression(flag);
+ break;
+ case TK_CONST_CAST:
+ expr = CRTTI_Parse_const_cast();
+ break;
+ case TK_DYNAMIC_CAST:
+ expr = CRTTI_Parse_dynamic_cast();
+ break;
+ case TK_REINTERPRET_CAST:
+ expr = CRTTI_Parse_reinterpret_cast();
+ break;
+ case TK_STATIC_CAST:
+ expr = CRTTI_Parse_static_cast();
+ break;
+ case TK_TYPEID:
+ expr = CRTTI_ParseTypeID();
+ break;
+ }
+ } else {
+ expr = primary_expression(flag);
+ }
+
+loop:
+ switch (tk) {
+ case '[':
+ expr = pointer_generation(expr);
+ tk = lex();
+ subexpr = expression();
+ if (copts.cplusplus && CExpr_CheckOperator('[', expr, subexpr, &conv)) {
+ if ((expr = conv.x0)) {
+ if (tk != ']')
+ CError_ErrorSkip(125);
+ else
+ tk = lex();
+ goto loop;
+ }
+
+#line 2753
+ CError_ASSERT((expr = conv.left));
+ CError_ASSERT((subexpr = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(expr->rtype)) {
+ expr = padd(expr, subexpr);
+ } else if (IS_TYPE_POINTER(subexpr->rtype)) {
+ expr = padd(subexpr, expr);
+ } else {
+ CError_Error(148);
+ goto dont_do_indirect;
+ }
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TPTR_TARGET(expr->rtype);
+ dont_do_indirect:
+ if (tk != ']')
+ CError_ErrorSkip(125);
+ else
+ tk = lex();
+ goto loop;
+
+ case '(':
+ funcexpr = CExpr_PointerGeneration(expr);
+ if (copts.cplusplus) {
+ if (CExpr_CheckOperator('(', funcexpr, NULL, &conv)) {
+#line 2775
+ CError_ASSERT((expr = conv.x0));
+ goto loop;
+ }
+ if (ENODE_IS(funcexpr, EMFPOINTER)) {
+ expr = checkreference(call_ptmf(funcexpr));
+ goto loop;
+ }
+ }
+
+ tk = lex();
+ args = CExpr_ScanExpressionList(1);
+ if (tk != ')')
+ CError_Error(115);
+
+ if (ENODE_IS(funcexpr, ETEMPLDEP)) {
+ expr = CExpr_NewENode(EFUNCCALL);
+ expr->rtype = &sttemplexpr;
+ expr->data.funccall.funcref = funcexpr;
+ expr->data.funccall.args = args;
+ expr->data.funccall.functype = &rt_func;
+ tk = lex();
+ } else {
+ expr = checkreference(CExpr_MakeFunctionCall(funcexpr, args));
+ tk = lex();
+ }
+ goto loop;
+
+ case TK_ARROW:
+ expr = pointer_generation(expr);
+ if (copts.cplusplus) {
+ while (IS_TYPE_CLASS(expr->rtype) && CExpr_CheckOperator(TK_ARROW, expr, NULL, &conv)) {
+#line 2810
+ CError_ASSERT((subexpr = conv.x0));
+ expr = pointer_generation(subexpr);
+ }
+ }
+
+ if (!IS_TYPE_POINTER(expr->rtype)) {
+ CError_ErrorSkip(148);
+ return expr;
+ }
+
+ if (copts.cplusplus && copts.objective_c && CObjC_IsType_id(expr->rtype)) {
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TPTR_TARGET(expr->rtype);
+ if ((subexpr = CObjC_CheckModernSendMessage(NULL, expr)))
+ return subexpr;
+ } else {
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TPTR_TARGET(expr->rtype);
+ }
+ case '.':
+ expr = pointer_generation(expr);
+ if (IS_TYPE_CLASS(expr->rtype)) {
+ CDecl_CompleteType(expr->rtype);
+ if (TYPE_CLASS(expr->rtype)->objcinfo && copts.cplusplus && (subexpr = CObjC_CheckModernSendMessage(expr->rtype, expr)))
+ return subexpr;
+
+ if (!(TYPE_CLASS(expr->rtype)->flags & CLASS_FLAGS_2))
+ CError_Error(136, expr->rtype, 0);
+
+ if ((tk = lex()) == TK_TEMPLATE && (tk = lex()) != TK_IDENTIFIER)
+ CError_Error(107);
+
+ if (CScope_ParseMemberName(TYPE_CLASS(expr->rtype), &pr, 0)) {
+ if (pr.x1C) {
+ if ((tk = lex()) == '(') {
+ if ((tk = lex()) != ')')
+ CError_Error(115);
+ else
+ tk = lex();
+ } else {
+ CError_Error(114);
+ }
+
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = &stvoid;
+ } else {
+ expr = checkreference(CExpr_ParseNameResultExpr(&pr, expr, 0, 0));
+ }
+ }
+ goto loop;
+ }
+ if (!IS_TYPE_STRUCT(expr->rtype) || TYPE_STRUCT(expr->rtype)->stype > STRUCT_TYPE_3) {
+ if (copts.cplusplus && (subexpr = CExpr_DummyDestr(expr)))
+ return subexpr;
+ CError_ErrorSkip(149);
+ return expr;
+ }
+ if (!ENODE_IS(expr, EINDIRECT)) {
+ subexpr = CExpr_NewETEMPNode(expr->rtype, 1);
+ copy = lalloc(sizeof(ENode));
+ *copy = *subexpr;
+
+ tmp = makemonadicnode(subexpr, EINDIRECT);
+ tmp->rtype = expr->rtype;
+
+ tmp = makediadicnode(tmp, expr, EASS);
+ tmp = makediadicnode(tmp, copy, ECOMMA);
+ tmp->rtype = copy->rtype;
+
+ tmp = makemonadicnode(tmp, EINDIRECT);
+ tmp->rtype = expr->rtype;
+ expr = tmp;
+ }
+ if ((tk = lex()) != TK_IDENTIFIER) {
+ CError_Error(107);
+ return expr;
+ }
+
+ member = ismember(TYPE_STRUCT(expr->rtype), tkidentifier);
+ if (!member) {
+ if (!expr->rtype->size)
+ CError_Error(136, expr->rtype, 0);
+ else
+ CError_Error(150, tkidentifier->name);
+ return expr;
+ }
+
+ if (!IS_TYPE_POINTER(expr->data.monadic->rtype)) {
+ CError_ErrorSkip(149);
+ return expr;
+ }
+
+ expr = checkreference(CClass_AccessMember(expr, member->type, member->qual, member->offset));
+ tk = lex();
+ goto loop;
+
+ case TK_INCREMENT:
+ tmp = pointer_generation(expr);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_INCREMENT, tmp, nullnode(), &conv)) {
+ if ((expr = conv.x0)) {
+ tk = lex();
+ goto loop;
+ }
+#line 2952
+ CError_ASSERT((tmp = conv.left));
+ }
+ tmp = CExpr_LValue(tmp, 1, 1);
+ if (tmp->rtype == TYPE(&stbool)) {
+ expr = CExpr_TempModifyExpr(tmp);
+ tk = lex();
+ } else {
+ checkadditive(tmp);
+ expr = makemonadicnode(tmp, EPOSTINC);
+ tk = lex();
+ }
+ goto loop;
+
+ case TK_DECREMENT:
+ tmp = pointer_generation(expr);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_DECREMENT, tmp, nullnode(), &conv)) {
+ if ((expr = conv.x0)) {
+ tk = lex();
+ goto loop;
+ }
+#line 2976
+ CError_ASSERT((tmp = conv.left));
+ }
+ tmp = CExpr_LValue(tmp, 1, 1);
+ checkadditive(tmp);
+ expr = makemonadicnode(tmp, EPOSTDEC);
+ tk = lex();
+ goto loop;
+ }
+
+ return expr;
+}
+
+static ENode *CExpr_ParseSizeof(void) {
+ Type *type;
+ ENode *expr;
+
+ type = CExpr_ParseTypeExpression(NULL);
+ if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)
+ CError_Error(286);
+
+ if (CTemplTool_IsTemplateArgumentDependentType(type)) {
+ expr = CExpr_NewTemplDepENode(TDE_TYPEEXPR);
+ expr->data.templdep.u.typeexpr.u.type = type;
+ return expr;
+ }
+
+ if (type->size == 0) {
+ if (copts.gcc_extensions && (IS_TYPE_FUNC(type) || IS_TYPE_VOID(type)))
+ return intconstnode(CABI_GetSizeTType(), 1);
+
+ if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type))
+ CError_Error(136, type, 0);
+ else
+ CError_Error(146);
+ }
+
+ return intconstnode(CABI_GetSizeTType(), type->size);
+}
+
+SInt32 scansizeof(void) {
+ ENode *expr;
+
+ expr = CExpr_ParseSizeof();
+ if (!ENODE_IS(expr, EINTCONST)) {
+ CError_Error(190);
+ return 0;
+ }
+
+ return CInt64_GetULong(&expr->data.intval);
+}
+
+static ENode *CExpr_ParseAlignof(void) {
+ Type *type;
+ ENode *expr;
+ SInt16 align;
+
+ type = CExpr_ParseTypeExpression(NULL);
+ if (IS_TYPE_CLASS(type) && TYPE_CLASS(type)->sominfo)
+ CError_Error(364);
+
+ if (CTemplTool_IsTemplateArgumentDependentType(type)) {
+ expr = CExpr_NewTemplDepENode(TDE_unk2);
+ expr->data.templdep.u.typeexpr.u.type = type;
+ return expr;
+ }
+
+ if (type->size == 0) {
+ if (IS_TYPE_CLASS(type) || IS_TYPE_STRUCT(type))
+ CError_Error(136, type, 0);
+ else
+ CError_Error(146);
+ }
+
+ align = CMach_GetTypeAlign(type);
+ if (align == 0)
+ align = 1;
+
+ return intconstnode(CABI_GetSizeTType(), align);
+}
+
+SInt32 scanalignof(void) {
+ ENode *expr;
+
+ expr = CExpr_ParseAlignof();
+ if (!ENODE_IS(expr, EINTCONST)) {
+ CError_Error(190);
+ return 0;
+ }
+
+ return CInt64_GetULong(&expr->data.intval);
+}
+
+static ENode *logicalexpression(ENode *expr) {
+ if (copts.cplusplus && copts.booltruefalse)
+ expr->rtype = TYPE(&stbool);
+ else
+ expr->rtype = TYPE(&stsignedint);
+ return expr;
+}
+
+ENode *getnodeaddress(ENode *expr, Boolean flag) {
+ ENode *result;
+ Object *obj;
+
+ if (!ENODE_IS(expr, EINDIRECT)) {
+ expr = CExpr_LValue(expr, flag, flag);
+ if (!ENODE_IS(expr, EINDIRECT)) {
+ if (!flag)
+ CError_Error(142);
+ return nullnode();
+ }
+ } else {
+ if (flag &&
+ ENODE_IS(expr->data.monadic, EOBJREF) &&
+ expr->data.monadic->data.objref->name == this_name_node &&
+ cscope_currentfunc &&
+ cscope_currentclass &&
+ expr->data.monadic->data.objref == CClass_ThisSelfObject())
+ CError_Error(189);
+ }
+
+ result = lalloc(sizeof(ENode));
+ *result = *expr;
+restart:
+ switch (result->data.monadic->type) {
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ result->type = ETYPCON;
+ if (IS_TYPE_POINTER_ONLY(result->rtype))
+ result->flags = TPTR_QUAL(result->rtype) & ENODE_FLAG_QUALS;
+ result->rtype = CDecl_NewPointerType(result->rtype);
+ return result;
+ case EOBJREF:
+ obj = result->data.monadic->data.objref;
+ if (obj->datatype == DALIAS) {
+ CExpr_AliasTransform(result->data.monadic);
+ goto restart;
+ }
+ if (obj->datatype == DINLINEFUNC)
+ CError_Error(175);
+ obj->flags |= OBJECT_FLAGS_2;
+ if (flag && !copts.cplusplus && obj->sclass == TK_REGISTER)
+ CError_Error(163);
+ break;
+ case EFUNCCALL:
+ if (flag && !IS_TYPE_POINTER_ONLY(result->data.monadic->data.funccall.functype->functype))
+ CError_Warning(142);
+ break;
+ case EBITFIELD:
+ CError_Error(144);
+ return nullnode();
+ }
+
+ switch (result->rtype->type) {
+ case TYPEPOINTER:
+ result->data.monadic->rtype = CDecl_NewPointerType(result->rtype);
+ result->data.monadic->flags = result->flags;
+ break;
+ default:
+ result->data.monadic->rtype = CDecl_NewPointerType(result->rtype);
+ result->data.monadic->flags = result->flags;
+ }
+
+ return result->data.monadic;
+}
+
+static ENode *CExpr_MakeStaticMemberList(NameSpaceObjectList *list) {
+ NameSpaceObjectList *newlist;
+ NameSpaceObjectList *n;
+ ENode *result;
+
+ newlist = NULL;
+ while (list) {
+ if (list->object->otype == OT_OBJECT && IS_TYPE_STATIC_METHOD(OBJECT(list->object)->type)) {
+ n = galloc(sizeof(NameSpaceObjectList));
+ *n = *list;
+ n->next = newlist;
+ newlist = n;
+ }
+ list = list->next;
+ }
+
+ if (!newlist) {
+ CError_Warning(331);
+ return nullnode();
+ }
+
+ result = CExpr_NewENode(EOBJLIST);
+ result->rtype = OBJECT(newlist->object)->type;
+ result->data.objlist.list = newlist;
+ return result;
+}
+
+static ENode *CExpr_MakePTDM(ENode *expr) {
+ ENode *result;
+
+#line 3414
+ CError_ASSERT(ENODE_IS(expr, EMEMBER) && expr->data.emember->list->object->otype == OT_MEMBERVAR);
+
+ result = nullnode();
+ result->rtype = CExpr_NewPTMType(expr->data.emember, NULL);
+ CInt64_SetLong(&result->data.intval, OBJ_MEMBER_VAR(expr->data.emember->list->object)->offset + 1);
+ return result;
+}
+
+ENode *getpointertomemberfunc(ENode *expr, Type *type, Boolean flag) {
+ NameSpaceObjectList *list;
+ Object *obj;
+ Object *dataobj;
+ Type *ptmtype;
+ TypeMethod *tmethod;
+ OLinkList *olist;
+ SInt32 data[3];
+
+#line 3442
+ CError_ASSERT(ENODE_IS(expr, EMEMBER));
+
+ if (expr->data.emember->expr && !copts.cpp_extensions)
+ CError_Error(141);
+
+ if (!copts.cpp_extensions) {
+ if (!(expr->data.emember->x11 && expr->data.emember->pr_1D)) {
+ if (type && IS_TYPE_MEMBERPOINTER(type))
+ CError_Warning(331);
+ }
+ }
+
+ if (expr->data.emember->list->next) {
+ if (type) {
+ if (IS_TYPE_MEMBERPOINTER(type)) {
+ type = TYPE_MEMBER_POINTER(type)->ty1;
+ for (list = expr->data.emember->list; list; list = list->next) {
+ if (list->object->otype == OT_OBJECT && is_memberpointerequal(OBJECT(list->object)->type, type)) {
+ obj = OBJECT(list->object);
+ break;
+ }
+ }
+ if (!list) {
+ CError_Error(146);
+ return nullnode();
+ }
+ } else {
+ return CExpr_MakeStaticMemberList(expr->data.emember->list);
+ }
+ } else {
+ obj = OBJECT(expr->data.emember->list->object);
+ }
+ } else {
+ obj = OBJECT(expr->data.emember->list->object);
+ }
+
+ while (obj->datatype == DALIAS)
+ obj = obj->u.alias.object;
+
+#line 3503
+ CError_ASSERT(obj->otype == OT_OBJECT && IS_TYPE_NONSTATIC_METHOD(obj->type));
+
+ if (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_100000)
+ CError_Error(190);
+
+ ptmtype = CExpr_NewPTMType(expr->data.emember, obj);
+ tmethod = TYPE_METHOD(obj->type);
+ dataobj = CParser_NewGlobalDataObject(NULL);
+ dataobj->name = CParser_GetUniqueName();
+ dataobj->nspace = cscope_root;
+ dataobj->type = ptmtype;
+ dataobj->sclass = TK_STATIC;
+
+ if (flag) {
+ data[0] = 0;
+ if (obj->datatype == DVFUNC) {
+ olist = NULL;
+ data[1] = tmethod->x1E;
+ data[2] = tmethod->theclass->vtable->offset;
+ } else {
+ data[1] = -1;
+ data[2] = 0;
+ olist = galloc(sizeof(OLinkList));
+ olist->next = NULL;
+ olist->obj = obj;
+ olist->somevalue = 0;
+ olist->offset = 8;
+ }
+ CInit_DeclareData(dataobj, data, olist, dataobj->type->size);
+ }
+
+ return create_objectnode(dataobj);
+}
+
+static ENode *getpointertomember(ENode *expr) {
+#line 3554
+ CError_ASSERT(ENODE_IS(expr, EMEMBER));
+
+ if (expr->data.emember->expr)
+ CError_Error(141);
+
+ expr->data.emember->x11 = 1;
+ if (!expr->data.emember->list->next) {
+ if (expr->data.emember->list->object->otype == OT_MEMBERVAR)
+ return CExpr_MakePTDM(expr);
+ else
+ return getpointertomemberfunc(expr, NULL, 1);
+ }
+
+ return expr;
+}
+
+ENode *CExpr_New_ELOGNOT_Node(ENode *input) {
+ ENode *expr;
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(input->rtype))
+ return CTempl_MakeTemplDepExpr(NULL, ELOGNOT, input);
+
+ expr = pointer_generation(input);
+ if (copts.cplusplus && CExpr_CheckOperator('!', expr, NULL, &conv)) {
+ if ((input = conv.x0))
+ return input;
+#line 3593
+ CError_ASSERT((expr = conv.left));
+ }
+
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ break;
+ case TYPEENUM:
+ expr = forceintegral(expr);
+ break;
+ case TYPEMEMBERPOINTER:
+ expr = CExpr_ConvertToCondition(expr);
+ break;
+ default:
+ CError_Error(144);
+ return expr;
+ }
+
+ switch (expr->type) {
+ case EINTCONST:
+ expr->data.intval = CInt64_Not(expr->data.intval);
+ break;
+ case EFLOATCONST:
+ expr->type = EINTCONST;
+ CInt64_SetLong(&expr->data.intval, CMach_FloatIsZero(expr->data.floatval));
+ break;
+ default:
+ expr = makemonadicnode(expr, ELOGNOT);
+ }
+
+ return logicalexpression(expr);
+}
+
+ENode *CExpr_New_EMONMIN_Node(ENode *input) {
+ ENode *expr;
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(input->rtype))
+ return CTempl_MakeTemplDepExpr(NULL, EMONMIN, input);
+
+ expr = pointer_generation(input);
+ if (copts.cplusplus && CExpr_CheckOperator('-', expr, NULL, &conv)) {
+ if ((input = conv.x0))
+ return input;
+#line 3652
+ CError_ASSERT((expr = conv.left));
+ }
+
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEENUM:
+ expr = integralpromote(expr);
+ if (ENODE_IS(expr, EINTCONST)) {
+ expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '-', expr->data.intval);
+ return expr;
+ }
+ return makemonadicnode(expr, EMONMIN);
+ case TYPEFLOAT:
+ if (ENODE_IS(expr, EFLOATCONST)) {
+ expr->data.floatval = CMach_CalcFloatMonadic(expr->rtype, '-', expr->data.floatval);
+ return expr;
+ }
+ return CExpr_UnaryFloatExpression(makemonadicnode(expr, EMONMIN));
+ default:
+ CError_Error(144);
+ return expr;
+ }
+}
+
+ENode *CExpr_New_EBINNOT_Node(ENode *input) {
+ ENode *expr;
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(input->rtype))
+ return CTempl_MakeTemplDepExpr(NULL, EBINNOT, input);
+
+ expr = pointer_generation(input);
+ if (copts.cplusplus && CExpr_CheckOperator('~', expr, NULL, &conv)) {
+ if ((input = conv.x0))
+ return input;
+#line 3702
+ CError_ASSERT((expr = conv.left));
+ }
+
+ expr = integralpromote(expr);
+
+ if (ENODE_IS(expr, EINTCONST)) {
+ expr->data.intval = CMach_CalcIntMonadic(expr->rtype, '~', expr->data.intval);
+ return expr;
+ }
+ return makemonadicnode(expr, EBINNOT);
+}
+
+ENode *unary_expression(void) {
+ ENode *expr;
+ ENode *tmp;
+ Conversion conv;
+
+ switch (tk) {
+ case TK_COLON_COLON:
+ switch (lookahead()) {
+ case TK_NEW:
+ tk = lex();
+ return scannew(1);
+ case TK_DELETE:
+ tk = lex();
+ return scandelete(1);
+ }
+ return postfix_expression(0);
+
+ case TK_NEW:
+ return scannew(0);
+ case TK_DELETE:
+ return scandelete(0);
+ case TK_INCREMENT:
+ tk = lex();
+ if (copts.cplusplus) {
+ expr = pointer_generation(cast_expression());
+ if (CExpr_CheckOperator(TK_INCREMENT, expr, NULL, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 3748
+ CError_ASSERT((expr = conv.left));
+ }
+ } else {
+ expr = pointer_generation(unary_expression());
+ }
+ expr = CExpr_LValue(expr, 1, 1);
+ if (expr->rtype == TYPE(&stbool)) {
+ tmp = nullnode();
+ tmp->rtype = TYPE(&stbool);
+ CInt64_SetLong(&tmp->data.intval, 1);
+ return makediadicnode(expr, tmp, EASS);
+ } else {
+ checkadditive(expr);
+ return makemonadicnode(expr, EPREINC);
+ }
+ case TK_DECREMENT:
+ tk = lex();
+ if (copts.cplusplus) {
+ expr = pointer_generation(cast_expression());
+ if (CExpr_CheckOperator(TK_DECREMENT, expr, NULL, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 3776
+ CError_ASSERT((expr = conv.left));
+ }
+ } else {
+ expr = pointer_generation(unary_expression());
+ }
+ expr = CExpr_LValue(expr, 1, 1);
+ checkadditive(expr);
+ return makemonadicnode(expr, EPREDEC);
+
+ case '&':
+ if (copts.cplusplus) {
+ switch ((tk = lex())) {
+ case TK_IDENTIFIER:
+ case TK_INHERITED:
+ case TK_COLON_COLON:
+ expr = postfix_expression(1);
+ if (ENODE_IS(expr, EMEMBER))
+ return getpointertomember(expr);
+ break;
+ default:
+ expr = cast_expression();
+ }
+
+ if (CExpr_CheckOperator('&', expr, NULL, &conv)) {
+#line 3809
+ CError_ASSERT(conv.x0);
+ return conv.x0;
+ }
+ } else {
+ tk = lex();
+ expr = cast_expression();
+ }
+
+ if (copts.mpwc_relax && !copts.cplusplus && IS_TYPE_ARRAY(expr->rtype) && ENODE_IS(expr, EINDIRECT))
+ return pointer_generation(expr);
+ if (ENODE_IS(expr, EOBJLIST))
+ return expr;
+
+ if (IS_TYPE_TEMPLDEPEXPR(expr->rtype)) {
+ tmp = CExpr_NewTemplDepENode(TDE_MONAND);
+ tmp->data.templdep.u.monadic = expr;
+ return tmp;
+ }
+
+ return getnodeaddress(expr, 1);
+
+ case '*':
+ tk = lex();
+ expr = pointer_generation(cast_expression());
+ if (copts.cplusplus && CExpr_CheckOperator('*', expr, NULL, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 3840
+ CError_ASSERT((expr = conv.left));
+ }
+
+ if (!IS_TYPE_POINTER(expr->rtype)) {
+ CError_Error(148);
+ return expr;
+ }
+
+ tmp = makemonadicnode(expr, EINDIRECT);
+ CDecl_CompleteType(tmp->rtype = TPTR_TARGET(tmp->rtype));
+ return tmp;
+
+ case '+':
+ tk = lex();
+ expr = pointer_generation(cast_expression());
+ if (copts.cplusplus && CExpr_CheckOperator('+', expr, NULL, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 3852
+ CError_ASSERT((expr = conv.left));
+ }
+
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEENUM:
+ return integralpromote(expr);
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ return expr;
+ default:
+ CError_Error(144);
+ return expr;
+ }
+
+ case '-':
+ tk = lex();
+ return CExpr_New_EMONMIN_Node(cast_expression());
+ case '~':
+ tk = lex();
+ return CExpr_New_EBINNOT_Node(cast_expression());
+ case '!':
+ tk = lex();
+ return CExpr_New_ELOGNOT_Node(cast_expression());
+
+ case TK_SIZEOF:
+ return CExpr_ParseSizeof();
+ case TK_UU_ALIGNOF_UU:
+ return CExpr_ParseAlignof();
+
+ case TK_LOGICAL_AND:
+ if (copts.ANSI_strict)
+ break;
+
+ if ((tk = lex()) != TK_IDENTIFIER) {
+ CError_Error(107);
+ return nullnode();
+ }
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = ELABEL;
+ expr->cost = 0;
+ expr->flags = 0;
+ expr->rtype = TYPE(&void_ptr);
+ expr->data.label = findlabel();
+ if (!expr->data.label) {
+ expr->data.label = newlabel();
+ expr->data.label->name = tkidentifier;
+ expr->data.label->next = Labels;
+ Labels = expr->data.label;
+ }
+ tk = lex();
+ return expr;
+ }
+
+ return postfix_expression(0);
+}
+
+ENode *do_castnullcheck(ENode *condexpr, ENode *nullcheckexpr) {
+ ENode *result;
+
+ if (isnotzero(nullcheckexpr))
+ return condexpr;
+
+ result = lalloc(sizeof(ENode));
+ *result = *condexpr;
+ result->type = ENULLCHECK;
+ result->data.nullcheck.nullcheckexpr = lalloc(sizeof(ENode));
+ *result->data.nullcheck.nullcheckexpr = *nullcheckexpr;
+ result->data.nullcheck.condexpr = condexpr;
+ result->data.nullcheck.precompid = CParser_GetUniqueID();
+
+ nullcheckexpr->type = EPRECOMP;
+ nullcheckexpr->data.precompid = result->data.nullcheck.precompid;
+
+ return result;
+}
+
+ENode *CExpr_SafeClassPointerCast(ENode *expr, TypeClass *a, TypeClass *b, Boolean typconflag, Boolean pathcheckflag) {
+ ENode *result;
+
+ result = CClass_ClassPointerCast(expr, a, b, typconflag, 1, pathcheckflag);
+ if (result != expr) {
+ if (!(ENODE_IS(result, ETYPCON) && result->data.monadic == expr))
+ result = do_castnullcheck(result, expr);
+ }
+ return result;
+}
+
+ENode *PointerToMemberCast(ENode *expr, TypeMemberPointer *tm1, TypeMemberPointer *tm2, Boolean flag) {
+ BClassList *path;
+ Boolean negate;
+ short depth;
+ Boolean isambig;
+ SInt32 pathoffset;
+ CInt64 pathoffset64;
+ ENode *tmp;
+
+#line 3984
+ CError_ASSERT(IS_TYPE_CLASS(tm1->ty2));
+#line 3985
+ CError_ASSERT(IS_TYPE_CLASS(tm2->ty2));
+
+ if (tm1->ty2 == tm2->ty2) {
+ expr->rtype = TYPE(tm2);
+ return expr;
+ }
+
+ negate = 0;
+ path = CClass_GetBasePath(TYPE_CLASS(tm2->ty2), TYPE_CLASS(tm1->ty2), &depth, &isambig);
+ if (!path) {
+ path = CClass_GetBasePath(TYPE_CLASS(tm1->ty2), TYPE_CLASS(tm2->ty2), &depth, &isambig);
+ if (!path)
+ goto failed;
+ negate = 1;
+ }
+
+ if (isambig)
+ CError_Error(188);
+
+ if ((pathoffset = CClass_GetPathOffset(path)) < 0)
+ goto failed;
+ if (negate)
+ pathoffset = -pathoffset;
+
+ if (flag)
+ CClass_CheckPathAccess(path, NULL, ACCESSPUBLIC);
+
+ if (tm1->size != tm2->size) {
+ failed:
+ CError_Error(247, tm1, 0, tm2, 0);
+ return nullnode();
+ }
+
+ if (!pathoffset) {
+ expr->rtype = TYPE(tm2);
+ return expr;
+ }
+
+ if (tm1->size == 4u) {
+ if (ENODE_IS(expr, EINTCONST)) {
+ if (!CInt64_IsZero(&expr->data.intval)) {
+ CInt64_SetLong(&pathoffset64, pathoffset);
+ expr->data.intval = CInt64_Add(expr->data.intval, pathoffset64);
+ }
+ expr->rtype = TYPE(tm2);
+ return expr;
+ } else {
+ expr->rtype = TYPE(&stunsignedlong);
+ tmp = intconstnode(TYPE(&stunsignedlong), pathoffset);
+ tmp = makediadicnode(expr, tmp, EADD);
+ tmp = makemonadicnode(tmp, ETYPCON);
+ tmp->rtype = TYPE(tm2);
+ return do_castnullcheck(tmp, expr);
+ }
+ } else {
+ tmp = create_temp_node(TYPE(&ptmstruct));
+ expr = getnodeaddress(expr, 0);
+ tmp = funccallexpr(rt_ptmf_cast, intconstnode(TYPE(&stsignedlong), pathoffset), expr, tmp, NULL);
+ tmp = makemonadicnode(tmp, EINDIRECT);
+ tmp->rtype = TYPE(tm2);
+ return tmp;
+ }
+}
+
+ENode *CExpr_MemberPointerConversion(ENode *expr, TypeMemberPointer *type, Boolean flag1) {
+ if (ENODE_IS(expr, EINTCONST) && CInt64_IsZero(&expr->data.intval)) {
+ if (IS_TYPE_FUNC(type->ty1))
+ expr = create_objectnode(rt_ptmf_null);
+ expr->rtype = TYPE(type);
+ } else if (ENODE_IS(expr, EMEMBER)) {
+ expr = getpointertomemberfunc(expr, TYPE(type), flag1);
+ }
+
+ return expr;
+}
+
+static ENode *CExpr_MemberPointerCast(ENode *expr, TypeMemberPointer *type, UInt32 qual) {
+ if (!IS_TYPE_MEMBERPOINTER(expr->rtype))
+ expr = CExpr_MemberPointerConversion(expr, type, 1);
+
+ if (!IS_TYPE_MEMBERPOINTER(expr->rtype)) {
+ CError_Error(164);
+ return nullnode();
+ }
+
+ expr = PointerToMemberCast(expr, TYPE_MEMBER_POINTER(expr->rtype), type, 0);
+ expr->flags = qual & ENODE_FLAG_QUALS;
+ return expr;
+}
+
+ENode *do_typecast(ENode *expr, Type *type, UInt32 qual) {
+ TypePointer *tptr;
+ ENode *tmp;
+ UInt32 flags;
+
+ if (!copts.old_argmatch)
+ return CExpr_Convert(expr, type, qual, 1, 0);
+
+ if (copts.cpp_extensions && is_typesame(expr->rtype, type) && !ENODE_IS(expr, EOBJLIST)) {
+ expr->rtype = type;
+ expr->flags &= ~ENODE_FLAG_QUALS;
+ expr->flags |= qual & ENODE_FLAG_QUALS;
+ return expr;
+ }
+
+ switch (type->type) {
+ case TYPEARRAY:
+ CError_Error(247, expr->rtype, ENODE_QUALS(expr), type, qual);
+ return expr;
+ case TYPEMEMBERPOINTER:
+ if (!IS_TYPE_CLASS(expr->rtype))
+ return CExpr_MemberPointerCast(expr, TYPE_MEMBER_POINTER(type), qual);
+ }
+
+ flags = qual & ENODE_FLAG_QUALS;
+
+ if (ENODE_IS(expr, EOBJLIST))
+ return CExpr_AssignmentPromotion(expr, type, flags, 1);
+
+ if (ENODE_IS(expr, EOBJREF) && IS_TYPE_NONSTATIC_METHOD(expr->data.objref->type)) {
+ CError_Error(221);
+ return nullnode();
+ }
+
+ if (type == &stvoid) {
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (IS_TYPE_REFERENCE(type)) {
+ tmp = getnodeaddress(expr, 0);
+ tptr = galloc(sizeof(TypePointer));
+ *tptr = *TYPE_POINTER(type);
+ tptr->qual &= ~Q_REFERENCE;
+
+ tmp = do_typecast(tmp, TYPE(tptr), qual);
+ tmp = makemonadicnode(tmp, EINDIRECT);
+ tmp->rtype = TPTR_TARGET(type);
+ tmp->flags = flags;
+ return tmp;
+ }
+
+ if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type)) {
+ if (expr->rtype->size == 0)
+ CDecl_CompleteType(expr->rtype);
+
+ if (expr->rtype == type && !CClass_CopyConstructor(TYPE_CLASS(type)))
+ return expr;
+
+ if (user_assign_check(expr, type, qual, 1, 1, 1)) {
+ assign_node->flags = flags;
+ return assign_node;
+ }
+
+ CError_Error(247, expr->rtype, ENODE_QUALS(expr), type, qual);
+ return nullnode();
+ }
+
+ if (IS_TYPE_STRUCT(type) && copts.cplusplus && is_typesame(expr->rtype, type)) {
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (type == TYPE(&stbool)) {
+ expr = CExpr_ConvertToBool(expr, 1);
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (IS_TYPE_ENUM(type)) {
+ tmp = do_typecast(expr, TYPE_ENUM(type)->enumtype, qual);
+ if (!ENODE_IS(tmp, EINTCONST))
+ tmp = makemonadicnode(tmp, ETYPCON);
+ tmp->rtype = type;
+ tmp->flags = flags;
+ return tmp;
+ }
+
+ if (IS_TYPE_INT_OR_FLOAT(type)) {
+ if (ENODE_IS(expr, ETYPCON) && expr->rtype->type == type->type && expr->rtype->size == type->size) {
+ if (is_unsigned(expr->rtype) == is_unsigned(type) && ENODE_QUALS(expr) == qual) {
+ expr->rtype = type;
+ expr->flags |= ENODE_FLAG_80;
+ return expr;
+ }
+ }
+
+ if (IS_TYPE_ENUM(expr->rtype))
+ expr = forceintegral(expr);
+
+ if (IS_TYPE_INT_OR_FLOAT(expr->rtype)) {
+ expr = promote(expr, type);
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (!(IS_TYPE_POINTER_ONLY(expr->rtype) && !IS_TYPE_FLOAT(type)))
+ CError_Error(247, expr->rtype, ENODE_QUALS(expr), type, qual);
+
+ if (ENODE_IS(expr, ETYPCON) && ENODE_IS(tmp = expr->data.monadic, EINTCONST)) {
+ tmp->rtype = type;
+ tmp->flags = flags;
+ tmp->data.intval = CExpr_IntConstConvert(type, TYPE(&stunsignedlong), tmp->data.intval);
+ return tmp;
+ }
+
+ if (type->size != 4) {
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = TYPE(&stunsignedlong);
+ }
+
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (IS_TYPE_POINTER(type)) {
+ if (IS_TYPE_POINTER(expr->rtype)) {
+ if (IS_TYPE_CLASS(TPTR_TARGET(expr->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(type)))
+ expr = CExpr_SafeClassPointerCast(expr, TYPE_CLASS(TPTR_TARGET(expr->rtype)), TYPE_CLASS(TPTR_TARGET(type)), 1, 0);
+
+ if (!ENODE_IS(expr, ETYPCON))
+ expr = makemonadicnode(expr, ETYPCON);
+
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+
+ if (!IS_TYPE_INT(expr->rtype)) {
+ if (!IS_TYPE_ENUM(expr->rtype)) {
+ CError_Error(247, expr->rtype, ENODE_QUALS(expr), type, qual);
+ return expr;
+ }
+ expr = forceintegral(expr);
+ }
+
+ if (expr->rtype->size != 4) {
+ if (!ENODE_IS(expr, EINTCONST))
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = TYPE(&stunsignedlong);
+ }
+
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+
+ if ((tmp = CodeGen_HandleTypeCast(expr, type, qual)))
+ return tmp;
+
+ CError_Error(247, expr->rtype, ENODE_QUALS(expr), type, qual);
+ return nullnode();
+}
+
+static Boolean isvectorconst(ENode *node) {
+ if (ENODE_IS3(node, ECOMMA, EINTCONST, EFLOATCONST))
+ return 1;
+ else
+ return 0;
+}
+
+ENode *cast_expression(void) {
+ ENode *expr;
+ ENode *tmp;
+ ENodeList *args;
+ MWVector128 vec;
+ DeclInfo di;
+
+ if (!(tk == '(' && islookaheaddeclaration()))
+ return unary_expression();
+ tk = lex();
+
+ memclrw(&di, sizeof(DeclInfo));
+ CParser_GetDeclSpecs(&di, 0);
+ scandeclarator(&di);
+
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ if (di.name)
+ CError_Error(164);
+
+ if (copts.altivec_model && tk == '(' && IS_TYPE_VECTOR(di.thetype)) {
+ tk = lex();
+ expr = s_expression();
+ if (tk != ')')
+ CError_ErrorSkip(115);
+ else
+ tk = lex();
+
+ if (CodeGen_CollapseVectorExpression(expr, &vec, di.thetype)) {
+ tmp = lalloc(sizeof(ENode));
+ tmp->type = EVECTOR128CONST;
+ if ((tmp->cost = expr->cost) == 0)
+ tmp->cost = 1;
+ tmp->flags = ENODE_QUALS(expr);
+ tmp->rtype = di.thetype;
+ tmp->data.vector128val = vec;
+ } else {
+ tmp = makemonadicnode(expr, ETYPCON);
+ }
+ tmp->rtype = di.thetype;
+ tmp->flags = expr->flags;
+ return tmp;
+ }
+
+ if (tk == '{' && (!copts.ANSI_strict || copts.c9x) && !IS_TYPE_VECTOR(di.thetype))
+ return CInit_AutoObject(NULL, di.thetype, di.qual);
+
+ expr = cast_expression();
+ if (copts.cplusplus && (CTemplTool_IsTemplateArgumentDependentType(di.thetype) ||
+ CTemplTool_IsTemplateArgumentDependentExpression(expr))) {
+ args = lalloc(sizeof(ENodeList));
+ args->next = NULL;
+ args->node = expr;
+ return CExpr_TemplArgDepCast(di.thetype, di.qual, args);
+ }
+
+ if (!IS_TYPE_REFERENCE(di.thetype))
+ expr = pointer_generation(expr);
+ return do_typecast(expr, di.thetype, di.qual);
+}
+
+static ENode *pm_expression(void) {
+ ENode *left;
+ ENode *right;
+ ENode *tmp;
+ Type *type;
+ UInt32 qual;
+ short flags;
+ Conversion conv;
+
+ left = cast_expression();
+restart:
+ switch (tk) {
+ case TK_ARROW_STAR:
+ left = pointer_generation(left);
+ tk = lex();
+ right = pointer_generation(cast_expression());
+
+ if (CExpr_CheckOperator(TK_ARROW_STAR, left, right, &conv)) {
+#line 4457
+ CError_ASSERT((left = conv.x0));
+ goto restart;
+ }
+
+ if (!IS_TYPE_POINTER(left->rtype)) {
+ CError_Error(148);
+ return left;
+ }
+
+ left = makemonadicnode(left, EINDIRECT);
+ left->rtype = TPTR_TARGET(left->rtype);
+ goto common_part;
+ case TK_DOT_STAR:
+ left = pointer_generation(left);
+ tk = lex();
+ right = pointer_generation(cast_expression());
+ if (!ENODE_IS(left, EINDIRECT)) {
+ CError_Error(142);
+ return left;
+ }
+ common_part:
+ if (!IS_TYPE_CLASS(left->rtype)) {
+ CError_Error(149);
+ return left;
+ }
+ if (!IS_TYPE_MEMBERPOINTER(right->rtype)) {
+ CError_Error(144);
+ return left;
+ }
+ if (left->rtype != TYPE_MEMBER_POINTER(right->rtype)->ty2) {
+ if (CClass_IsBaseClass(TYPE_CLASS(left->rtype), TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2), NULL, 1, 1)) {
+ left->data.monadic = CClass_ClassPointerCast(
+ left->data.monadic,
+ TYPE_CLASS(left->rtype),
+ TYPE_CLASS(TYPE_MEMBER_POINTER(right->rtype)->ty2),
+ 0, 1, 1);
+ left->rtype = TYPE_MEMBER_POINTER(right->rtype)->ty2;
+ } else {
+ CError_Error(146);
+ return left;
+ }
+ }
+ type = CClass_CombineClassAccessQualifiers(
+ TYPE_MEMBER_POINTER(right->rtype)->ty1,
+ ENODE_QUALS(right),
+ left->flags,
+ &qual);
+ flags = qual;
+ if (!IS_TYPE_FUNC(type)) {
+ if (!ENODE_IS(right, EINTCONST)) {
+ if (!canadd(left->data.monadic, -1)) {
+ left->data.monadic = makediadicnode(left->data.monadic, nullnode(), EADD);
+ CInt64_SetLong(&left->data.monadic->data.diadic.right->data.intval, -1);
+ optimizecomm(left->data.monadic);
+ }
+ right->rtype = TYPE(&stunsignedlong);
+ left->data.monadic = makediadicnode(left->data.monadic, right, EADD);
+ optimizecomm(left->data.monadic);
+ } else {
+ right->data.intval = CInt64_Sub(right->data.intval, cint64_one);
+ if (!canadd2(left->data.monadic, right->data.intval)) {
+ right->rtype = TYPE(&stunsignedlong);
+ left->data.monadic = makediadicnode(left->data.monadic, right, EADD);
+ optimizecomm(left->data.monadic);
+ }
+ }
+
+ if (IS_TYPE_BITFIELD(type)) {
+ left->data.monadic = makemonadicnode(left->data.monadic, EBITFIELD);
+ left->data.monadic->rtype = type;
+ left->rtype = TYPE_BITFIELD(type)->bitfieldtype;
+ } else {
+ left->rtype = type;
+ }
+ left->flags = flags;
+ left = checkreference(left);
+ goto restart;
+ } else {
+#line 4535
+ CError_ASSERT(ENODE_IS(right, EINDIRECT));
+ tmp = lalloc(sizeof(ENode));
+ tmp->type = EMFPOINTER;
+ tmp->cost = 4;
+ tmp->flags = 0;
+ tmp->rtype = &stvoid;
+ tmp->data.mfpointer.accessnode = left;
+ tmp->data.mfpointer.mfpointer = right;
+ return tmp;
+ }
+ default:
+ return left;
+ }
+}
+
+ENode *CExpr_New_EMUL_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EMUL, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('*', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4566
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ return makemultnode(left, right);
+}
+
+ENode *CExpr_New_EDIV_Node(ENode *left, ENode *right, Boolean no_warning) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EDIV, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('/', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4592
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ return makedivnode(left, right, no_warning);
+}
+
+ENode *CExpr_New_EMODULO_Node(ENode *left, ENode *right, Boolean no_warning) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EMODULO, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('%', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4618
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+ CExpr_ArithmeticConversion(&left, &right);
+
+ if (iszero(right)) {
+ if (!no_warning)
+ CError_Warning(139);
+ return left;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '%', right->data.intval);
+ return left;
+ }
+
+ if (iszero(left))
+ return makediadicnode(right, left, ECOMMA);
+
+ if (CExpr_IsOne(right)) {
+ right = nullnode();
+ right->rtype = left->rtype;
+ return makediadicnode(left, right, ECOMMA);
+ }
+
+ return makediadicnode(left, right, EMODULO);
+}
+
+ENode *CExpr_New_EADD_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EADD, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('+', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4665
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ return makeaddnode(left, right);
+}
+
+ENode *CExpr_New_ESUB_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ESUB, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('-', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4690
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ return makesubnode(left, right);
+}
+
+ENode *CExpr_New_ESHL_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ESHL, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_SHL, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4715
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+
+ if (iszero(left) || iszero(right)) {
+ return left;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHL, right->data.intval);
+ return left;
+ }
+
+ return makediadicnode(left, right, ESHL);
+}
+
+ENode *CExpr_New_ESHR_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ESHR, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_SHR, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4752
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+
+ if (iszero(left) || iszero(right)) {
+ return left;
+ }
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_SHR, right->data.intval);
+ return left;
+ }
+
+ return makediadicnode(left, right, ESHR);
+}
+
+static ENode *pointercompare(ENodeType nt, ENode *left, ENode *right) {
+ Type *ltype;
+ Type *rtype;
+
+ ltype = left->rtype;
+ rtype = right->rtype;
+ if (IS_TYPE_POINTER_ONLY(ltype) && IS_TYPE_POINTER_ONLY(rtype)) {
+ ltype = TPTR_TARGET(left->rtype);
+ rtype = TPTR_TARGET(right->rtype);
+ if (IS_TYPE_CLASS(ltype) && IS_TYPE_CLASS(rtype)) {
+ if (ltype != rtype) {
+ if (ltype == TPTR_TARGET(left->rtype)) {
+ if (CClass_IsBaseClass(TYPE_CLASS(ltype), TYPE_CLASS(rtype), NULL, 0, 1)) {
+ left = CExpr_SafeClassPointerCast(left, TYPE_CLASS(ltype), TYPE_CLASS(rtype), 0, 1);
+ } else if (CClass_IsBaseClass(TYPE_CLASS(rtype), TYPE_CLASS(ltype), NULL, 0, 1)) {
+ right = CExpr_SafeClassPointerCast(right, TYPE_CLASS(rtype), TYPE_CLASS(ltype), 0, 1);
+ } else {
+ CError_Error(245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ }
+ } else {
+ CError_Error(245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ }
+ }
+ } else if (!is_typeequal(left->rtype, right->rtype)) {
+ if (!copts.objective_c || !CObjC_IsCompatibleType(left->rtype, right->rtype)) {
+ CError_Error(245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ }
+ }
+ } else if (nt == EEQU || nt == ENOTEQU) {
+ if (IS_TYPE_INT(ltype)) {
+ if (!(ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval)))
+ CError_Error(144);
+#line 4847
+ CError_ASSERT(IS_TYPE_POINTER_ONLY(rtype));
+ left->rtype = TYPE(&stunsignedlong);
+ } else if (IS_TYPE_INT(rtype)) {
+ if (!(ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval)))
+ CError_Error(144);
+#line 4855
+ CError_ASSERT(IS_TYPE_POINTER_ONLY(ltype));
+ right->rtype = TYPE(&stunsignedlong);
+ } else if (!is_typeequal(ltype, rtype)) {
+ CError_Error(245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ }
+ } else {
+ if (!is_typeequal(ltype, rtype))
+ CError_Error(245, left->rtype, ENODE_QUALS(left), right->rtype, ENODE_QUALS(right));
+ }
+
+ return logicalexpression(makediadicnode(left, right, nt));
+}
+
+static ENode *unsigncheck(ENode *expr, Boolean flag1, Boolean flag2) {
+ if (is_unsigned(expr->data.diadic.left->rtype)) {
+ if (ENODE_IS(expr->data.diadic.left, EINTCONST) && CInt64_IsZero(&expr->data.diadic.left->data.intval)) {
+ flag1 = !flag1;
+ } else if (!(ENODE_IS(expr->data.diadic.right, EINTCONST) && CInt64_IsZero(&expr->data.diadic.right->data.intval))) {
+ return logicalexpression(expr);
+ }
+
+ if (flag1 && flag2) {
+ expr->type = EEQU;
+ return logicalexpression(expr);
+ }
+ if (!flag1 && !flag2) {
+ expr->type = ENOTEQU;
+ return logicalexpression(expr);
+ }
+ return CExpr_ConstResult(logicalexpression(expr), !flag1);
+ }
+ return logicalexpression(expr);
+}
+
+ENode *CExpr_New_ELESS_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ELESS, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('<', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4929
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(ELESS, left, right);
+
+ CExpr_CompareConvert(&left, "<", &right, 0);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '<', right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '<', right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = unsigncheck(makediadicnode(left, right, ELESS), 1, 0);
+ }
+
+ return left;
+}
+
+ENode *CExpr_New_ELESSEQU_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ELESSEQU, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_LESS_EQUAL, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 4976
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(ELESSEQU, left, right);
+
+ CExpr_CompareConvert(&left, "<=", &right, 0);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LESS_EQUAL, right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LESS_EQUAL, right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = unsigncheck(makediadicnode(left, right, ELESSEQU), 1, 1);
+ }
+
+ return left;
+}
+
+ENode *CExpr_New_EGREATER_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EGREATER, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('>', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5023
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(EGREATER, left, right);
+
+ CExpr_CompareConvert(&left, ">", &right, 0);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '>', right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, '>', right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = unsigncheck(makediadicnode(left, right, EGREATER), 0, 0);
+ }
+
+ return left;
+}
+
+ENode *CExpr_New_EGREATEREQU_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EGREATEREQU, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_GREATER_EQUAL, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5070
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(EGREATEREQU, left, right);
+
+ CExpr_CompareConvert(&left, ">=", &right, 0);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_GREATER_EQUAL, right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_GREATER_EQUAL, right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = unsigncheck(makediadicnode(left, right, EGREATEREQU), 0, 1);
+ }
+
+ return left;
+}
+
+ENode *memberpointercompare(ENodeType nt, ENode *left, ENode *right) {
+ Object *func;
+ ENodeList *arg;
+
+ if (!IS_TYPE_MEMBERPOINTER(left->rtype)) {
+ if (!(IS_TYPE_INT(left->rtype) && ENODE_IS(left, EINTCONST) && CInt64_IsZero(&left->data.intval))) {
+ CError_Error(144);
+ return nullnode();
+ }
+ } else if (!IS_TYPE_MEMBERPOINTER(right->rtype)) {
+ if (!(IS_TYPE_INT(right->rtype) && ENODE_IS(right, EINTCONST) && CInt64_IsZero(&right->data.intval))) {
+ CError_Error(144);
+ return nullnode();
+ }
+ } else if (!is_typeequal(left->rtype, right->rtype)) {
+ left = PointerToMemberCast(left, TYPE_MEMBER_POINTER(left->rtype), TYPE_MEMBER_POINTER(right->rtype), 1);
+ }
+
+ if ((ENODE_IS(left, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(left->rtype)->ty1)) && (ENODE_IS(right, EINTCONST) || !IS_TYPE_FUNC(TYPE_MEMBER_POINTER(right->rtype)->ty1))) {
+ left->rtype = TYPE(&stunsignedlong);
+ right->rtype = TYPE(&stunsignedlong);
+ return logicalexpression(makediadicnode(left, right, nt));
+ }
+
+ arg = lalloc(sizeof(ENodeList));
+ if (ENODE_IS(left, EINTCONST) || ENODE_IS(right, EINTCONST)) {
+ func = rt_ptmf_test;
+ if (ENODE_IS(left, EINTCONST))
+ arg->node = getnodeaddress(right, 0);
+ else
+ arg->node = getnodeaddress(left, 0);
+ arg->next = NULL;
+ } else {
+ func = rt_ptmf_cmpr;
+ arg->next = lalloc(sizeof(ENodeList));
+ arg->node = getnodeaddress(left, 0);
+ arg->next->node = getnodeaddress(right, 0);
+ arg->next->next = NULL;
+ }
+
+ left = lalloc(sizeof(ENode));
+ left->type = EFUNCCALL;
+ left->rtype = TYPE(&stsignedlong);
+ left->cost = 4;
+ left->data.funccall.funcref = create_objectrefnode(func);
+ left->data.funccall.args = arg;
+ left->data.funccall.functype = TYPE_FUNC(func->type);
+ left->flags = TYPE_FUNC(func->type)->qual & ENODE_FLAG_QUALS;
+
+ if (nt == EEQU)
+ left = makemonadicnode(left, ELOGNOT);
+
+ return left;
+}
+
+ENode *CExpr_New_EEQU_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EEQU, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_EQ, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5201
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(EEQU, left, right);
+ if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype))
+ return memberpointercompare(EEQU, left, right);
+
+ CExpr_CompareConvert(&left, "==", &right, 1);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_EQ, right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ left->type = EINTCONST;
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_EQ, right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = makediadicnode(left, right, EEQU);
+ optimizecomm(left);
+ }
+
+ return logicalexpression(left);
+}
+
+ENode *CExpr_New_ENOTEQU_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ENOTEQU, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_NE, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5261
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ if (IS_TYPE_POINTER(left->rtype) || IS_TYPE_POINTER(right->rtype))
+ return pointercompare(ENOTEQU, left, right);
+ if (IS_TYPE_MEMBERPOINTER(left->rtype) || IS_TYPE_MEMBERPOINTER(right->rtype))
+ return memberpointercompare(ENOTEQU, left, right);
+
+ CExpr_CompareConvert(&left, "!=", &right, 1);
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, TK_LOGICAL_NE, right->data.intval);
+ left->rtype = CParser_GetBoolType();
+ } else if (ENODE_IS(left, EFLOATCONST) && ENODE_IS(right, EFLOATCONST)) {
+ CInt64_SetLong(&left->data.intval, CMach_CalcFloatDiadicBool(left->rtype, left->data.floatval, TK_LOGICAL_NE, right->data.floatval));
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ } else {
+ left = makediadicnode(left, right, ENOTEQU);
+ optimizecomm(left);
+ }
+
+ return logicalexpression(left);
+}
+
+ENode *CExpr_New_EAND_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EAND, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('&', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5321
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+ CExpr_ArithmeticConversion(&left, &right);
+
+ if (iszero(left) || CExpr_AllBitsSet(right))
+ return left;
+ if (iszero(right) || CExpr_AllBitsSet(left))
+ return right;
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '&', right->data.intval);
+ return left;
+ }
+
+ left = makediadicnode(left, right, EAND);
+ optimizecomm(left);
+ return left;
+}
+
+ENode *CExpr_New_EXOR_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EXOR, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('^', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5360
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+ CExpr_ArithmeticConversion(&left, &right);
+
+ if (iszero(right))
+ return left;
+ if (iszero(left))
+ return right;
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '^', right->data.intval);
+ return left;
+ }
+
+ left = makediadicnode(left, right, EXOR);
+ optimizecomm(left);
+ return left;
+}
+
+ENode *CExpr_New_EOR_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, EOR, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator('|', left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5399
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ left = integralpromote(left);
+ right = integralpromote(right);
+ CExpr_ArithmeticConversion(&left, &right);
+
+ if (iszero(right) || CExpr_AllBitsSet(left))
+ return left;
+ if (iszero(left) || CExpr_AllBitsSet(right))
+ return right;
+
+ if (ENODE_IS(left, EINTCONST) && ENODE_IS(right, EINTCONST)) {
+ left->data.intval = CMach_CalcIntDiadic(left->rtype, left->data.intval, '|', right->data.intval);
+ return left;
+ }
+
+ left = makediadicnode(left, right, EOR);
+ optimizecomm(left);
+ return left;
+}
+
+ENode *CExpr_New_ELAND_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ELAND, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_AND, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5438
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ switch (left->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ break;
+ case TYPEENUM:
+ case TYPEMEMBERPOINTER:
+ left = CExpr_ConvertToCondition(left);
+ break;
+ default:
+ CError_Error(144);
+ left = nullnode();
+ }
+ switch (right->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ break;
+ case TYPEENUM:
+ case TYPEMEMBERPOINTER:
+ right = CExpr_ConvertToCondition(right);
+ break;
+ default:
+ CError_Error(144);
+ right = nullnode();
+ }
+
+ if (iszero(left)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 0);
+ return left;
+ }
+
+ if (isnotzero(left)) {
+ if (iszero(right)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 0);
+ return left;
+ } else if (isnotzero(right)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 1);
+ return left;
+ } else {
+ left = makemonadicnode(right, ELOGNOT);
+ left->rtype = CParser_GetBoolType();
+ return makemonadicnode(left, ELOGNOT);
+ }
+ } else {
+ if (isnotzero(right)) {
+ left = makemonadicnode(left, ELOGNOT);
+ left->rtype = CParser_GetBoolType();
+ return makemonadicnode(left, ELOGNOT);
+ } else if (iszero(right)) {
+ right->type = EINTCONST;
+ right->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&right->data.intval, 0);
+ return makecommaexpression(left, right);
+ } else {
+ left = makediadicnode(left, right, ELAND);
+ left->rtype = CParser_GetBoolType();
+ return left;
+ }
+ }
+}
+
+ENode *CExpr_New_ELOR_Node(ENode *left, ENode *right) {
+ Conversion conv;
+
+ if (IS_TYPE_TEMPLDEPEXPR(left->rtype) || IS_TYPE_TEMPLDEPEXPR(right->rtype))
+ return CTempl_MakeTemplDepExpr(left, ELOR, right);
+
+ left = pointer_generation(left);
+ right = pointer_generation(right);
+ if (copts.cplusplus && CExpr_CheckOperator(TK_LOGICAL_OR, left, right, &conv)) {
+ if (conv.x0)
+ return conv.x0;
+#line 5543
+ CError_ASSERT((left = conv.left));
+ CError_ASSERT((right = conv.right));
+ }
+
+ switch (left->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ break;
+ case TYPEENUM:
+ case TYPEMEMBERPOINTER:
+ left = CExpr_ConvertToCondition(left);
+ break;
+ default:
+ CError_Error(144);
+ left = nullnode();
+ }
+ switch (right->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ case TYPEARRAY:
+ break;
+ case TYPEENUM:
+ case TYPEMEMBERPOINTER:
+ right = CExpr_ConvertToCondition(right);
+ break;
+ default:
+ CError_Error(144);
+ right = nullnode();
+ }
+
+ if (isnotzero(left)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 1);
+ return left;
+ }
+
+ if (iszero(left)) {
+ if (iszero(right)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 0);
+ return left;
+ } else if (isnotzero(right)) {
+ left->type = EINTCONST;
+ left->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&left->data.intval, 1);
+ return left;
+ } else {
+ left = makemonadicnode(right, ELOGNOT);
+ left->rtype = CParser_GetBoolType();
+ return makemonadicnode(left, ELOGNOT);
+ }
+ } else {
+ if (isnotzero(right)) {
+ right->type = EINTCONST;
+ right->rtype = CParser_GetBoolType();
+ CInt64_SetLong(&right->data.intval, 1);
+ } else if (iszero(right)) {
+ left = makemonadicnode(left, ELOGNOT);
+ left->rtype = CParser_GetBoolType();
+ return makemonadicnode(left, ELOGNOT);
+ }
+ left = makediadicnode(left, right, ELOR);
+ left->rtype = CParser_GetBoolType();
+ return left;
+ }
+}
+
+ENode *CExpr_NewDyadicNode(ENode *left, ENodeType nt, ENode *right) {
+ switch (nt) {
+ default:
+#line 5642
+ CError_FATAL();
+ case EADD: return CExpr_New_EADD_Node(left, right);
+ case ESUB: return CExpr_New_ESUB_Node(left, right);
+ case EMUL: return CExpr_New_EMUL_Node(left, right);
+ case EDIV: return CExpr_New_EDIV_Node(left, right, 1);
+ case EMODULO: return CExpr_New_EMODULO_Node(left, right, 1);
+ case EAND: return CExpr_New_EAND_Node(left, right);
+ case EXOR: return CExpr_New_EXOR_Node(left, right);
+ case EOR: return CExpr_New_EOR_Node(left, right);
+ case ESHL: return CExpr_New_ESHL_Node(left, right);
+ case ESHR: return CExpr_New_ESHR_Node(left, right);
+ case ELESS: return CExpr_New_ELESS_Node(left, right);
+ case EGREATER: return CExpr_New_EGREATER_Node(left, right);
+ case ELESSEQU: return CExpr_New_ELESSEQU_Node(left, right);
+ case EGREATEREQU: return CExpr_New_EGREATEREQU_Node(left, right);
+ case EEQU: return CExpr_New_EEQU_Node(left, right);
+ case ENOTEQU: return CExpr_New_ENOTEQU_Node(left, right);
+ case ELAND: return CExpr_New_ELAND_Node(left, right);
+ case ELOR: return CExpr_New_ELOR_Node(left, right);
+ }
+}
+
+typedef struct DyadicInfo {
+ ENodeType t;
+ UInt8 prec;
+} DyadicInfo;
+
+static Boolean CExpr_GetDyadicInfo(short token, DyadicInfo *info) {
+ switch (token) {
+ case '*':
+ info->t = EMUL;
+ info->prec = 20;
+ return 1;
+ case '/':
+ info->t = EDIV;
+ info->prec = 20;
+ return 1;
+ case '%':
+ info->t = EMODULO;
+ info->prec = 20;
+ return 1;
+ case '+':
+ info->t = EADD;
+ info->prec = 19;
+ return 1;
+ case '-':
+ info->t = ESUB;
+ info->prec = 19;
+ return 1;
+ case TK_SHL:
+ info->t = ESHL;
+ info->prec = 18;
+ return 1;
+ case TK_SHR:
+ info->t = ESHR;
+ info->prec = 18;
+ return 1;
+ case '<':
+ info->t = ELESS;
+ info->prec = 17;
+ return 1;
+ case TK_LESS_EQUAL:
+ info->t = ELESSEQU;
+ info->prec = 17;
+ return 1;
+ case '>':
+ if (disallowgreaterthan)
+ return 0;
+ info->t = EGREATER;
+ info->prec = 17;
+ return 1;
+ case TK_GREATER_EQUAL:
+ info->t = EGREATEREQU;
+ info->prec = 17;
+ return 1;
+ case TK_LOGICAL_EQ:
+ info->t = EEQU;
+ info->prec = 16;
+ return 1;
+ case TK_LOGICAL_NE:
+ info->t = ENOTEQU;
+ info->prec = 16;
+ return 1;
+ case '&':
+ info->t = EAND;
+ info->prec = 15;
+ return 1;
+ case '^':
+ info->t = EXOR;
+ info->prec = 14;
+ return 1;
+ case '|':
+ info->t = EOR;
+ info->prec = 13;
+ return 1;
+ case TK_LOGICAL_AND:
+ info->t = ELAND;
+ info->prec = 12;
+ return 1;
+ case TK_LOGICAL_OR:
+ info->t = ELOR;
+ info->prec = 11;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static ENode *CExpr_ParseDyadicExpression(ENode *left, UInt8 prec, Boolean no_warning) {
+ ENode *right;
+ Boolean is_eland_or_elor;
+ Boolean save_dgt;
+ Boolean cont;
+ DyadicInfo left_info;
+ DyadicInfo right_info;
+
+ save_dgt = disallowgreaterthan;
+ if (!left) {
+ disallowgreaterthan = 0;
+ left = pm_expression();
+ disallowgreaterthan = save_dgt;
+ }
+
+ do {
+ if (!CExpr_GetDyadicInfo(tk, &left_info))
+ return left;
+
+ switch (left_info.t) {
+ case ELAND:
+ CExpr_CheckUnwantedAssignment(left);
+ if (iszero(left))
+ no_warning = 1;
+ is_eland_or_elor = 1;
+ break;
+ case ELOR:
+ CExpr_CheckUnwantedAssignment(left);
+ if (isnotzero(left))
+ no_warning = 1;
+ is_eland_or_elor = 1;
+ break;
+ default:
+ is_eland_or_elor = 0;
+ }
+
+ tk = lex();
+ disallowgreaterthan = 0;
+ right = pm_expression();
+ disallowgreaterthan = save_dgt;
+ inner_loop:
+ if (CExpr_GetDyadicInfo(tk, &right_info)) {
+ if (left_info.prec >= right_info.prec) {
+ cont = (prec >= right_info.prec);
+ } else {
+ right = CExpr_ParseDyadicExpression(right, left_info.prec, no_warning);
+ goto inner_loop;
+ }
+ } else {
+ cont = 1;
+ }
+
+ if (is_eland_or_elor)
+ CExpr_CheckUnwantedAssignment(right);
+
+ switch (left_info.t) {
+ case EDIV:
+ left = CExpr_New_EDIV_Node(left, right, no_warning);
+ break;
+ case EMODULO:
+ left = CExpr_New_EMODULO_Node(left, right, no_warning);
+ break;
+ default:
+ left = CExpr_NewDyadicNode(left, left_info.t, right);
+ }
+ } while (!cont);
+
+ return left;
+}
+
+static Boolean CExpr_IsBlockMoveType(Type *type) {
+ switch (type->type) {
+ case TYPESTRUCT:
+ case TYPECLASS:
+ return 1;
+ case TYPEMEMBERPOINTER:
+ return type->size != 4;
+ default:
+ return 0;
+ }
+}
+
+ENode *CExpr_New_ECOND_Node(ENode *cond, ENode *expr1, ENode *expr2) {
+ ENode *result;
+ ENodeList *args;
+ short cost;
+ Conversion conv;
+
+ cond = CExpr_ConvertToCondition(pointer_generation(cond));
+ expr1 = pointer_generation(expr1);
+ expr2 = pointer_generation(expr2);
+
+ if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) {
+ CError_Error(144);
+ return nullnode();
+ }
+
+ cost = cond->cost + 1;
+ if (expr1->cost > expr2->cost)
+ cost += expr1->cost;
+ else
+ cost += expr2->cost;
+ if (expr2->cost > cost)
+ cost = expr2->cost;
+ if (cost > 200)
+ cost = 200;
+
+ result = CExpr_NewENode(ECOND);
+ result->cost = cost;
+ result->rtype = expr1->rtype;
+ result->flags = expr1->flags | expr2->flags;
+ result->data.cond.cond = cond;
+ if (ENODE_IS(expr1, EFUNCCALL) && expr1->rtype == &stvoid && (expr1->flags & ENODE_FLAG_VOLATILE)) {
+ result->rtype = expr2->rtype;
+ result->flags = expr2->flags;
+ result->data.cond.expr1 = expr1;
+ result->data.cond.expr2 = expr2;
+ return result;
+ }
+ if (ENODE_IS(expr2, EFUNCCALL) && expr2->rtype == &stvoid && (expr2->flags & ENODE_FLAG_VOLATILE)) {
+ result->rtype = expr1->rtype;
+ result->flags = expr1->flags;
+ result->data.cond.expr1 = expr1;
+ result->data.cond.expr2 = expr2;
+ return result;
+ }
+
+ if (
+ ENODE_IS(expr1, EINDIRECT) &&
+ ENODE_IS(expr2, EINDIRECT) &&
+ is_typesame(expr1->rtype, expr2->rtype) &&
+ ENODE_QUALS(expr1) == ENODE_QUALS(expr2) &&
+ CExpr_IsBlockMoveType(expr1->rtype) &&
+ !ENODE_IS(expr1->data.monadic, EBITFIELD) &&
+ !ENODE_IS(expr2->data.monadic, EBITFIELD)
+ ) {
+ if (isnotzero(cond))
+ return expr1;
+ if (iszero(cond))
+ return expr2;
+ result->data.cond.expr1 = getnodeaddress(expr1, 0);
+ result->data.cond.expr2 = getnodeaddress(expr2, 0);
+ result->rtype = result->data.cond.expr1->rtype;
+ result = makemonadicnode(result, EINDIRECT);
+ result->rtype = TPTR_TARGET(result->rtype);
+ return result;
+ }
+
+ if ((IS_TYPE_CLASS(expr1->rtype) || IS_TYPE_CLASS(expr2->rtype)) && !is_typesame(expr1->rtype, expr2->rtype)) {
+ if (!copts.old_argmatch) {
+ if (CExpr_CondOperatorMatch(expr1, expr2, &conv)) {
+#line 6246
+ CError_ASSERT(!conv.x0);
+ expr1 = conv.left;
+ expr2 = conv.right;
+ } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) {
+ if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1)))
+ CError_Error(188);
+ expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1);
+ } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) {
+ expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1);
+ } else {
+ goto failed;
+ }
+
+ result->rtype = expr1->rtype;
+ } else {
+ args = lalloc(sizeof(ENodeList));
+ args->node = expr1;
+ args->next = lalloc(sizeof(ENodeList));
+ args->next->node = expr2;
+ args->next->next = NULL;
+
+ if (CExpr_CheckOperatorConversion(':', expr1, expr2, args, &conv)) {
+#line 6274
+ CError_ASSERT(!conv.x0);
+ expr1 = conv.left;
+ expr2 = conv.right;
+ }
+
+ result->rtype = expr1->rtype;
+ }
+ }
+
+ switch (expr1->rtype->type) {
+ case TYPEENUM:
+ if (expr1->rtype == expr2->rtype)
+ break;
+ expr1 = forceintegral(expr1);
+ case TYPEINT:
+ if (IS_TYPE_POINTER_ONLY(expr2->rtype) || IS_TYPE_MEMBERPOINTER(expr2->rtype)) {
+ expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1);
+ result->rtype = expr2->rtype;
+ break;
+ }
+ case TYPEFLOAT:
+ if (expr1->rtype != expr2->rtype) {
+ CExpr_ArithmeticConversion(&expr1, &expr2);
+ result->rtype = expr1->rtype;
+ }
+ break;
+ case TYPEPOINTER:
+ if (ENODE_IS(expr2, EINTCONST) && CInt64_IsZero(&expr2->data.intval)) {
+ expr2->rtype = TYPE(&stunsignedlong);
+ break;
+ }
+ if (IS_TYPE_POINTER_ONLY(expr2->rtype)) {
+ if (IS_TYPE_CLASS(TPTR_TARGET(expr1->rtype)) && IS_TYPE_CLASS(TPTR_TARGET(expr2->rtype))) {
+ if (TPTR_TARGET(expr1->rtype) != TPTR_TARGET(expr2->rtype)) {
+ if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr1->rtype)), TYPE_CLASS(TPTR_TARGET(expr2->rtype)), NULL, 0, 1)) {
+ expr1 = CExpr_SafeClassPointerCast(
+ expr1,
+ TYPE_CLASS(TPTR_TARGET(expr1->rtype)),
+ TYPE_CLASS(TPTR_TARGET(expr2->rtype)),
+ 0, 1);
+ expr1->rtype = expr2->rtype;
+ } else if (CClass_IsBaseClass(TYPE_CLASS(TPTR_TARGET(expr2->rtype)), TYPE_CLASS(TPTR_TARGET(expr1->rtype)), NULL, 0, 1)) {
+ expr2 = CExpr_SafeClassPointerCast(
+ expr2,
+ TYPE_CLASS(TPTR_TARGET(expr2->rtype)),
+ TYPE_CLASS(TPTR_TARGET(expr1->rtype)),
+ 0, 1);
+ expr2->rtype = expr1->rtype;
+ } else {
+ goto failed;
+ }
+ }
+ result->rtype = expr1->rtype;
+ break;
+ }
+ if (TPTR_TARGET(expr2->rtype) == &stvoid)
+ result->rtype = expr2->rtype;
+ }
+ if (!is_typeequal(expr1->rtype, expr2->rtype)) {
+ if (!copts.objective_c)
+ goto failed;
+ if (!CObjC_IsCompatibleType(expr1->rtype, expr2->rtype))
+ goto failed;
+ expr1->rtype = expr2->rtype = CObjC_GetObjCType_id(1);
+ }
+ break;
+ case TYPEVOID:
+ if (!is_typeequal(expr1->rtype, expr2->rtype))
+ goto failed;
+ break;
+ case TYPESTRUCT:
+ case TYPECLASS:
+ if (!is_typeequal(expr1->rtype, expr2->rtype))
+ goto failed;
+ result->rtype = expr1->rtype;
+ break;
+ case TYPEMEMBERPOINTER:
+ if (IS_TYPE_MEMBERPOINTER(expr2->rtype) && TYPE_MEMBER_POINTER(expr1->rtype)->ty2 == TYPE_MEMBER_POINTER(expr2->rtype)->ty2) {
+ expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1);
+ } else if (CExpr_CanImplicitlyConvert(expr1, expr2->rtype, ENODE_QUALS(expr2))) {
+ if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1)))
+ CError_Error(188);
+ expr1 = CExpr_Convert(expr1, expr2->rtype, ENODE_QUALS(expr2), 0, 1);
+ } else if (CExpr_CanImplicitlyConvert(expr2, expr1->rtype, ENODE_QUALS(expr1))) {
+ expr2 = CExpr_Convert(expr2, expr1->rtype, ENODE_QUALS(expr1), 0, 1);
+ } else {
+ goto failed;
+ }
+ result->rtype = expr1->rtype;
+ break;
+ default:
+ failed:
+ CError_Error(245, expr1->rtype, ENODE_QUALS(expr1), expr2->rtype, ENODE_QUALS(expr2));
+ return nullnode();
+ }
+
+ result->data.cond.expr1 = expr1;
+ result->data.cond.expr2 = expr2;
+ if (isnotzero(cond))
+ result = expr1;
+ else if (iszero(cond))
+ result = expr2;
+ return result;
+}
+
+static ENode *conditional_expression(void) {
+ ENode *cond;
+ ENode *expr1;
+ ENode *expr2;
+ ENode *result;
+ Boolean is_templdep_cond;
+
+ is_templdep_cond = 0;
+ cond = CExpr_ParseDyadicExpression(NULL, 0, 0);
+ if (tk != '?')
+ return cond;
+
+ cond = pointer_generation(cond);
+ if (!IS_TYPE_TEMPLDEPEXPR(cond->rtype)) {
+ cond = CExpr_ConvertToCondition(cond);
+ if (!IS_TYPE_INT_OR_FLOAT(cond->rtype) && !IS_TYPE_POINTER_ONLY(cond->rtype)) {
+ CError_Error(144);
+ return nullnode();
+ }
+ } else {
+ is_templdep_cond = 1;
+ }
+
+ tk = lex();
+ expr1 = expression();
+ if (tk != ':')
+ CError_ErrorSkip(141);
+ else
+ tk = lex();
+
+ expr2 = (copts.cplusplus && !copts.ARM_conform) ? assignment_expression() : conditional_expression();
+
+ if (is_templdep_cond || IS_TYPE_TEMPLDEPEXPR(expr1->rtype) || IS_TYPE_TEMPLDEPEXPR(expr2->rtype)) {
+ result = CExpr_NewENode(ECOND);
+ result->rtype = &sttemplexpr;
+ result->data.cond.cond = cond;
+ result->data.cond.expr1 = expr1;
+ result->data.cond.expr2 = expr2;
+ return result;
+ }
+
+ return CExpr_New_ECOND_Node(cond, expr1, expr2);
+}
+
+static ENode *CExpr_MakeOpAssNode(ENode *left, ENode *right, ENodeType nt) {
+ if (left->rtype != right->rtype) {
+ switch (right->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ break;
+ case TYPEENUM:
+ right->rtype = TYPE_ENUM(right->rtype)->enumtype;
+ break;
+ default:
+ right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1);
+ }
+ if (IS_TYPE_FLOAT(left->rtype)) {
+ if (IS_TYPE_INT(right->rtype) || (IS_TYPE_FLOAT(right->rtype) && left->rtype->size >= right->rtype->size))
+ right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1);
+ } else if (IS_TYPE_INT(left->rtype)) {
+ if (IS_TYPE_INT(right->rtype) && (left->rtype->size > right->rtype->size || (left->rtype->size == right->rtype->size && is_unsigned(left->rtype) == is_unsigned(right->rtype))))
+ right = CExpr_AssignmentPromotion(right, left->rtype, 0, 1);
+ }
+ }
+
+ return makediadicnode(left, right, nt);
+}
+
+static ENode *makeassignmentnode(ENode *left, ENodeType nt, short token) {
+ ENode *right;
+ ENode *tmp;
+ ENode *funcexpr;
+ ENodeList *args;
+ Conversion conv;
+
+ tk = lex();
+ right = assignment_expression();
+ if (copts.cplusplus) {
+ if (copts.old_argmatch && !ENODE_IS(right, EMEMBER))
+ right = pointer_generation(right);
+ if (CExpr_CheckOperator(token, left, right, &conv)) {
+ if (!conv.x0) {
+ if (nt == EASS)
+ goto continue_anyway;
+#line 6531
+ CError_FATAL();
+ }
+ return conv.x0;
+ }
+ if (IS_TYPE_CLASS(left->rtype) && CClass_AssignmentOperator(TYPE_CLASS(left->rtype)))
+ CError_Error(144);
+ }
+continue_anyway:
+ if (IS_TYPE_ARRAY(left->rtype)) {
+ if (copts.gcc_extensions && nt == EASS && is_typesame(left->rtype, right->rtype)) {
+ tmp = makediadicnode(left, right, nt);
+ tmp->flags = left->flags;
+ return tmp;
+ }
+ CError_Error(144);
+ return nullnode();
+ }
+
+ left = CExpr_LValue(pointer_generation(left), 1, 1);
+ if (nt != EASS) {
+ if (!IS_TYPE_INT(right->rtype)) {
+ if (!IS_TYPE_ENUM(right->rtype)) {
+ CError_Error(144);
+ return left;
+ }
+ right = forceintegral(right);
+ }
+ if (!IS_TYPE_INT(left->rtype)) {
+ if (copts.cplusplus) {
+ CError_Error(144);
+ return left;
+ }
+ left = forceintegral(left);
+ if (!IS_TYPE_INT(left->rtype)) {
+ CError_Error(144);
+ return left;
+ }
+ }
+ return CExpr_MakeOpAssNode(left, right, nt);
+ }
+
+ if (IS_TYPE_CLASS(left->rtype) && TYPE_CLASS(left->rtype)->sominfo) {
+ CError_Error(285);
+ return left;
+ }
+
+ if (copts.warn_implicitconv && ENODE_IS(left, EINDIRECT) && ENODE_IS(left->data.monadic, EBITFIELD) && !ENODE_IS(right, EINTCONST)) {
+ copts.warn_implicitconv = 0;
+ right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1);
+ copts.warn_implicitconv = 1;
+ } else {
+ right = CExpr_AssignmentPromotion(right, left->rtype, left->flags, 1);
+ }
+
+ tmp = right;
+ if (IS_TYPE_FLOAT(right->rtype) && ENODE_IS(right, ETYPCON) && right->rtype->size == right->data.monadic->rtype->size)
+ tmp = right->data.monadic;
+
+ if (
+ ENODE_IS(left, EINDIRECT) &&
+ ENODE_IS(left->data.monadic, EOBJREF) &&
+ ENODE_IS(tmp, EINDIRECT) &&
+ (ENODE_IS(funcexpr = right->data.monadic, EFUNCCALL) || ENODE_IS(funcexpr, EFUNCCALLP)) &&
+ left->rtype == funcexpr->data.funccall.functype->functype &&
+ CMach_GetFunctionResultClass(funcexpr->data.funccall.functype) == 1 &&
+ (args = funcexpr->data.funccall.args)
+ ) {
+ switch (CABI_GetStructResultArgumentIndex(funcexpr->data.funccall.functype)) {
+ case 0:
+ break;
+ case 1:
+ if ((args = args->next))
+ break;
+#line 6625
+ CError_FATAL();
+ default:
+#line 6626
+ CError_FATAL();
+ }
+ if (ENODE_IS(args->node, ETEMP)) {
+ if (!(IS_TYPE_CLASS(left->rtype) && CClass_Destructor(TYPE_CLASS(left->rtype)))) {
+ args->node = getnodeaddress(left, 0);
+ return right;
+ }
+ }
+ }
+
+ right = makediadicnode(left, right, nt);
+ right->flags = left->flags;
+ return right;
+}
+
+static ENode *makepassignmentnode(ENode *left, ENodeType nt, short token) {
+ ENode *right;
+ Boolean is_array;
+ Conversion conv;
+
+ is_array = IS_TYPE_ARRAY(left->rtype);
+ left = pointer_generation(left);
+ if (copts.cplusplus) {
+ tk = lex();
+ right = pointer_generation(assignment_expression());
+ if (CExpr_CheckOperator(token, left, right, &conv)) {
+#line 6669
+ CError_ASSERT(conv.x0);
+ return conv.x0;
+ }
+ left = CExpr_LValue(left, 1, 1);
+ } else {
+ left = CExpr_LValue(left, 1, 1);
+ tk = lex();
+ right = pointer_generation(assignment_expression());
+ }
+
+ if (is_array)
+ CError_Error(144);
+
+ switch (left->rtype->type) {
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEPOINTER:
+ break;
+ case TYPEENUM:
+ if (copts.cplusplus) {
+ CError_Error(144);
+ return left;
+ }
+ left = forceintegral(left);
+ break;
+ default:
+ CError_Error(144);
+ return left;
+ }
+
+ if (IS_TYPE_ENUM(right->rtype))
+ right = forceintegral(right);
+
+ if (iszero(right))
+ return left;
+
+ if (IS_TYPE_POINTER_ONLY(left->rtype)) {
+ if (IS_TYPE_INT(right->rtype)) {
+ if (nt == ESUBASS) {
+ left = psub(left, right);
+ if (ENODE_IS(left, ESUB))
+ left->type = ESUBASS;
+ return left;
+ } else {
+ left = padd(left, right);
+ if (ENODE_IS(left, EADD))
+ left->type = EADDASS;
+ return left;
+ }
+ }
+ CError_Error(144);
+ return left;
+ } else {
+ return CExpr_MakeOpAssNode(left, right, nt);
+ }
+}
+
+static ENode *makemulassignmentnode(ENode *left, ENodeType nt, short token) {
+ ENode *right;
+ Boolean is_array;
+ Conversion conv;
+
+ is_array = IS_TYPE_ARRAY(left->rtype);
+ left = pointer_generation(left);
+ if (copts.cplusplus) {
+ tk = lex();
+ right = pointer_generation(assignment_expression());
+ if (CExpr_CheckOperator(token, left, right, &conv)) {
+#line 6753
+ CError_ASSERT(conv.x0);
+ return conv.x0;
+ }
+ if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) {
+ CError_Error(144);
+ return nullnode();
+ }
+ left = CExpr_LValue(left, 1, 1);
+ } else {
+ if (IS_TYPE_ENUM(left->rtype))
+ left = forceintegral(left);
+ if (!IS_TYPE_INT(left->rtype) && !(IS_TYPE_FLOAT(left->rtype) && nt != EMODASS)) {
+ CError_Error(144);
+ return nullnode();
+ }
+
+ left = CExpr_LValue(left, 1, 1);
+ tk = lex();
+ right = pointer_generation(assignment_expression());
+ }
+
+ if (is_array)
+ CError_Error(144);
+
+ if (IS_TYPE_ENUM(right->rtype))
+ right = forceintegral(right);
+
+ if (IS_TYPE_INT(left->rtype) && IS_TYPE_FLOAT(right->rtype) && nt == EMODASS) {
+ CError_Error(144);
+ return nullnode();
+ }
+
+ return CExpr_MakeOpAssNode(left, right, nt);
+}
+
+static ENode *CExpr_TransformOpAssign(ENode *expr) {
+ switch (expr->type) {
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ if (expr->rtype == TYPE(&stbool)) {
+ expr = CIRTrans_TransformOpAss(expr);
+ if (ENODE_IS(expr, EASS)) {
+ expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT);
+ expr->data.diadic.right->rtype = TYPE(&stbool);
+ expr->data.diadic.right = makemonadicnode(expr->data.diadic.right, ELOGNOT);
+ }
+ }
+ }
+
+ return expr;
+}
+
+ENode *assignment_expression(void) {
+ ENode *expr;
+
+ if (tk == TK_THROW)
+ return CExcept_ScanThrowExpression();
+
+ expr = conditional_expression();
+ switch (tk) {
+ case '=':
+ return makeassignmentnode(expr, EASS, tk);
+ case TK_ADD_ASSIGN:
+ return CExpr_TransformOpAssign(makepassignmentnode(expr, EADDASS, tk));
+ case TK_SUB_ASSIGN:
+ return CExpr_TransformOpAssign(makepassignmentnode(expr, ESUBASS, tk));
+ case TK_MULT_ASSIGN:
+ expr = makemulassignmentnode(expr, EMULASS, tk);
+ if (ENODE_IS(expr, EMULASS) && CExpr_IsOne(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return CExpr_TransformOpAssign(expr);
+ case TK_DIV_ASSIGN:
+ expr = makemulassignmentnode(expr, EDIVASS, tk);
+ if (ENODE_IS(expr, EDIVASS)) {
+ if (iszero(expr->data.diadic.right) && !IS_TYPE_FLOAT(expr->rtype)) {
+ CError_Warning(139);
+ return expr->data.diadic.left;
+ }
+ if (CExpr_IsOne(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ }
+ return CExpr_TransformOpAssign(expr);
+ case TK_MOD_ASSIGN:
+ expr = makemulassignmentnode(expr, EMODASS, tk);
+ if (ENODE_IS(expr, EMODASS)) {
+ if (iszero(expr->data.diadic.right)) {
+ CError_Warning(139);
+ return expr->data.diadic.left;
+ }
+ }
+ return CExpr_TransformOpAssign(expr);
+ case TK_SHL_ASSIGN:
+ expr = makeassignmentnode(expr, ESHLASS, tk);
+ if (ENODE_IS(expr, ESHLASS) && iszero(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return CExpr_TransformOpAssign(expr);
+ case TK_SHR_ASSIGN:
+ expr = makeassignmentnode(expr, ESHRASS, tk);
+ if (ENODE_IS(expr, ESHRASS) && iszero(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return CExpr_TransformOpAssign(expr);
+ case TK_AND_ASSIGN:
+ expr = makeassignmentnode(expr, EANDASS, tk);
+ if (ENODE_IS(expr, EANDASS) && CExpr_AllBitsSet(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return expr;
+ case TK_XOR_ASSIGN:
+ expr = makeassignmentnode(expr, EXORASS, tk);
+ if (ENODE_IS(expr, EXORASS) && iszero(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return CExpr_TransformOpAssign(expr);
+ case TK_OR_ASSIGN:
+ expr = makeassignmentnode(expr, EORASS, tk);
+ if (ENODE_IS(expr, EORASS) && iszero(expr->data.diadic.right))
+ return expr->data.diadic.left;
+ return CExpr_TransformOpAssign(expr);
+ default:
+ return expr;
+ }
+}
+
+ENode *conv_assignment_expression(void) {
+ return pointer_generation(assignment_expression());
+}
+
+static Boolean CExpr_HasSideEffect(ENode *expr) {
+ switch (expr->type) {
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EMUL:
+ case EDIV:
+ case EMODULO:
+ 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 EROTL:
+ case EROTR:
+ case EBITFIELD:
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case ETEMP:
+ case EARGOBJ:
+ case ELOCOBJ:
+ case EOBJLIST:
+ case EMEMBER:
+ case EVECTOR128CONST:
+ return 0;
+ case ETYPCON:
+ return IS_TYPE_VOID(expr->rtype);
+ case EINDIRECT:
+ switch (expr->data.monadic->type) {
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ return 1;
+ default:
+ return 0;
+ }
+ case ECOMMA:
+ return CInline_ExpressionHasSideEffect(expr->data.diadic.right);
+ case ECOND:
+ return CInline_ExpressionHasSideEffect(expr->data.cond.expr1) || CInline_ExpressionHasSideEffect(expr->data.cond.expr2);
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EFORCELOAD:
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ case EMFPOINTER:
+ case ENULLCHECK:
+ case EPRECOMP:
+ case ELABEL:
+ case ENEWEXCEPTION:
+ case ENEWEXCEPTIONARRAY:
+ case EMYSTERY67:
+ case EINSTRUCTION:
+ return 1;
+ default:
+#line 7056
+ CError_FATAL();
+ return 0;
+ }
+}
+
+void CExpr_CheckUnusedExpression(ENode *expr) {
+ ENode *scan;
+ ENodeList *arg;
+
+ if (copts.warn_possunwant) {
+ scan = expr;
+ while (ENODE_IS(scan, ETYPCON))
+ scan = scan->data.monadic;
+ if (ENODE_IS(scan, EEQU)) {
+ CError_Warning(208);
+ return;
+ }
+ }
+
+ if (copts.warn_no_side_effect) {
+ if (!CExpr_HasSideEffect(expr)) {
+ CError_Warning(369);
+ return;
+ }
+ }
+
+ if (copts.warn_resultnotused) {
+ scan = expr;
+ if (IS_TYPE_VOID(expr->rtype))
+ return;
+ if (ENODE_IS(expr, EINDIRECT))
+ scan = expr->data.monadic;
+
+ switch (scan->type) {
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ if (ENODE_IS(scan->data.funccall.funcref, EOBJREF) && scan->data.funccall.funcref->data.objref->name == asop_name_node)
+ return;
+ if (CMach_GetFunctionResultClass(scan->data.funccall.functype) == 1 && (arg = scan->data.funccall.args)) {
+ switch (CABI_GetStructResultArgumentIndex(scan->data.funccall.functype)) {
+ case 0:
+ break;
+ case 1:
+ if ((arg = arg->next))
+ break;
+#line 7110
+ CError_FATAL();
+ default:
+#line 7111
+ CError_FATAL();
+ }
+
+ if (!ENODE_IS(arg->node, ETEMP))
+ return;
+ }
+ CError_Warning(370);
+ }
+ }
+}
+
+ENode *s_expression(void) {
+ ENode *left;
+ ENode *right;
+ Conversion conv;
+
+ left = assignment_expression();
+ while (tk == ',') {
+ left = pointer_generation(left);
+ tk = lex();
+ right = pointer_generation(assignment_expression());
+
+ if (copts.cplusplus && CExpr_CheckOperator(',', left, right, &conv)) {
+#line 7143
+ CError_ASSERT((left = conv.x0));
+ } else {
+ CExpr_CheckUnusedExpression(left);
+ left = makecommaexpression(left, right);
+ left->rtype = right->rtype;
+ }
+ }
+
+ return left;
+}
+
+ENode *expression(void) {
+ return pointer_generation(s_expression());
+}
+
+CInt64 CExpr_IntegralConstExprType(Type **tint) {
+ ENode *expr;
+
+ expr = pointer_generation(conditional_expression());
+ if (ENODE_IS(expr, EINTCONST)) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ *tint = expr->rtype;
+ return expr->data.intval;
+ case TYPEENUM:
+ *tint = TYPE_ENUM(expr->rtype)->enumtype;
+ return expr->data.intval;
+ }
+ }
+
+ CError_Error(124);
+ *tint = TYPE(&stchar);
+ return cint64_zero;
+}
+
+ENode *CExpr_IntegralConstOrDepExpr(void) {
+ ENode *expr;
+
+ expr = pointer_generation(conditional_expression());
+ if (ENODE_IS(expr, EINTCONST)) {
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ return expr;
+ case TYPEENUM:
+ expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
+ return expr;
+ default:
+#line 7209
+ CError_FATAL();
+ }
+ }
+
+ if (CTemplTool_IsTemplateArgumentDependentExpression(expr))
+ return expr;
+
+ CError_Error(124);
+ expr = nullnode();
+ expr->rtype = TYPE(&stchar);
+ return expr;
+}
+
+CInt64 CExpr_IntegralConstExpr(void) {
+ Type *throwaway;
+ return CExpr_IntegralConstExprType(&throwaway);
+}
+
+void CExpr_CheckUnwantedAssignment(ENode *expr) {
+ if (copts.warn_possunwant) {
+ if (ENODE_IS(expr, EASS) && !(expr->flags & ENODE_FLAG_80))
+ CError_Warning(207);
+ }
+}
+
+Boolean CExpr_ParseAsmExpr(Object **objptr, CInt64 *valptr) {
+ ENode *expr;
+
+ if (objptr)
+ *objptr = NULL;
+ *valptr = cint64_zero;
+
+ expr = pointer_generation(assignment_expression());
+ if (ENODE_IS(expr, EINTCONST)) {
+ *valptr = expr->data.intval;
+ return 1;
+ }
+
+ if (objptr) {
+ switch (expr->type) {
+ case EINDIRECT:
+ if (CInit_RelocInitCheck(expr->data.monadic, objptr, valptr, 1))
+ return 1;
+ break;
+ case EOBJREF:
+ *objptr = expr->data.objref;
+ while ((*objptr)->datatype == DALIAS)
+ *objptr = (*objptr)->u.alias.object;
+ return 1;
+ case EMEMBER:
+ if (expr->data.emember->list->object->otype == OT_OBJECT) {
+ if (expr->data.emember->list->next && expr->data.emember->list->next->object->otype == OT_OBJECT)
+ CError_Error(199);
+ *objptr = OBJECT(expr->data.emember->list->object);
+ while ((*objptr)->datatype == DALIAS)
+ *objptr = (*objptr)->u.alias.object;
+ return 1;
+ }
+ break;
+ case EOBJLIST:
+ CError_Error(199);
+ return 0;
+ }
+ }
+
+ CError_Error(155);
+ return 0;
+}
diff --git a/compiler_and_linker/unsorted/CExpr2.c b/compiler_and_linker/unsorted/CExpr2.c
index 6679bce..47268ac 100644
--- a/compiler_and_linker/unsorted/CExpr2.c
+++ b/compiler_and_linker/unsorted/CExpr2.c
@@ -2,18 +2,22 @@
#include "compiler/CABI.h"
#include "compiler/CClass.h"
#include "compiler/CDecl.h"
+#include "compiler/CInit.h"
#include "compiler/CInt64.h"
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CInline.h"
#include "compiler/CMachine.h"
+#include "compiler/CMangler.h"
#include "compiler/CParser.h"
+#include "compiler/CPrepTokenizer.h"
#include "compiler/CScope.h"
#include "compiler/CodeGen.h"
#include "compiler/CompilerTools.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/scopes.h"
+#include "compiler/templates.h"
#ifdef __MWERKS__
#undef va_start
@@ -25,9 +29,18 @@
#endif
// TODO MOVE ME
+extern ENode *CObjC_New(TypeClass *tclass);
+extern Boolean CObjC_IsType_id(Type *type);
+extern ENode *CObjC_Delete(TypeClass *tclass, ENode *expr);
+extern ENode *CSOM_New(TypeClass *tclass);
+extern ENode *CSOM_Delete(TypeClass *tclass, ENode *expr);
extern ENode *CSOM_EnvCheck(ENode *, ENodeList *);
+extern ENode *CSOM_MethodAccess(BClassList *, Object *, Boolean);
extern Boolean CTemplTool_IsTemplateArgumentDependentExpression(ENode *expr);
extern ENode *CTemplTool_DeduceDefaultArg(Object *func, ENode *expr);
+extern Boolean CTempl_CanDeduceFunc(Object *func, TypeFunc *tfunc, TemplArg *templargs);
+extern void CTempl_FuncMatch(NameSpaceObjectList *nsol, TemplArg *templargs, ENodeList *argexprs, Match13 *match, ENode *expr);
+extern TemplFuncInstance *CTempl_DeduceFunc(Object *func, TypeFunc *tfunc, TemplArg *templargs, Object *anotherobj, Boolean flag);
extern Boolean CObjC_IsCompatibleType(Type *a, Type *b);
ENode *assign_node;
@@ -43,10 +56,9 @@ static CExprReplaceCB cexpr_rsearch_callback;
static Type *cexpr_left_conversion_type;
static Type *cexpr_right_conversion_type;
-// data objects, need to figure out the types
-static void *diadic_arg1;
-static void *diadic_arg2;
-static void *mon_arg;
+static FuncArg mon_arg = {NULL, NULL, NULL, NULL, 0, 0, 0, 0};
+static FuncArg diadic_arg2 = {NULL, NULL, NULL, NULL, 0, 0, 0, 0};
+static FuncArg diadic_arg1 = {&diadic_arg1, NULL, NULL, NULL, 0, 0, 0, 0};
static void CExpr_RecSearchExprTree(ENode *expr) {
ENodeList *list;
@@ -1147,9 +1159,9 @@ void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) {
while (IS_TYPE_POINTER_ONLY(t2) && IS_TYPE_POINTER_ONLY(t1)) {
if (r8) {
if ((TYPE_POINTER(t1)->qual & Q_CONST) != (TYPE_POINTER(t2)->qual & Q_CONST))
- match->xC--;
+ match->anotherm5.x8--;
if ((TYPE_POINTER(t1)->qual & Q_VOLATILE) != (TYPE_POINTER(t2)->qual & Q_VOLATILE))
- match->xC--;
+ match->anotherm5.x8--;
}
t2 = TYPE_POINTER(t2)->target;
t1 = TYPE_POINTER(t1)->target;
@@ -1157,9 +1169,9 @@ void CExpr_MatchCV(Type *t1, UInt32 q1, Type *t2, UInt32 q2, Match13 *match) {
}
if ((q1 & Q_CONST) != (q2 & Q_CONST))
- match->xC--;
+ match->anotherm5.x8--;
if ((q1 & Q_VOLATILE) != (q2 & Q_VOLATILE))
- match->xC--;
+ match->anotherm5.x8--;
}
Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match) {
@@ -1167,14 +1179,14 @@ Boolean CExpr_MatchAssign(Type *type, UInt32 qual, ENode *expr, Match13 *match)
case CheckResult0:
return 0;
case CheckResult1:
- match->x4++;
+ match->anotherm5.x0++;
break;
case CheckResult2:
- match->x6++;
+ match->anotherm5.x2++;
break;
case CheckResult3:
- match->x8++;
- match->xA += assign_value;
+ match->anotherm5.x4++;
+ match->anotherm5.x6 += assign_value;
break;
case CheckResult4:
match->xE++;
@@ -1216,7 +1228,35 @@ static short CExpr_StdMatchCompare(Match5 *a, Match5 *b, Boolean flag) {
}
static short CExpr2_MemberPointerConversion(Type *type, ENode *expr, Boolean flag1) {
- // returns CheckResult
+ ENode *newnode;
+ short depth;
+
+ newnode = lalloc(sizeof(ENode));
+ *newnode = *expr;
+ if (!IS_TYPE_MEMBERPOINTER(newnode->rtype)) {
+ newnode = CExpr_MemberPointerConversion(newnode, type, flag1);
+ if (iscpp_typeequal(newnode->rtype, type)) {
+ if (flag1)
+ assign_node = newnode;
+ return CheckResult3;
+ }
+ }
+
+ if (IS_TYPE_MEMBERPOINTER(newnode->rtype)) {
+#line 1656
+ CError_ASSERT(IS_TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2));
+#line 1657
+ CError_ASSERT(IS_TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2));
+
+ if (CClass_IsBaseClass(TYPE_CLASS(TYPE_MEMBER_POINTER(type)->ty2), TYPE_CLASS(TYPE_MEMBER_POINTER(newnode->rtype)->ty2), &depth, 0, 0)) {
+ assign_value = 1000 - depth;
+ if (flag1)
+ assign_node = PointerToMemberCast(newnode, TYPE_MEMBER_POINTER(newnode->rtype), TYPE_MEMBER_POINTER(type), 1);
+ return CheckResult3;
+ }
+ }
+
+ return CheckResult0;
}
ENode *CExpr_ClassPointerCast(BClassList *cls, ENode *origexpr, Boolean nullcheckflag) {
@@ -1347,6 +1387,75 @@ ENode *CExpr_GetClassAccessNode(BClassList *a, BClassList *b, ENode *expr, Objec
}
static short std_assign_check_overload(NameSpaceObjectList *list, TemplArg *templargs, Type *type, Boolean flag1) {
+ Object *obj;
+ Object *used_obj;
+ Boolean found_non_template_func;
+ Boolean is_ambig;
+ TemplFuncInstance *instance;
+ ENode *expr;
+ Object *cmp1;
+ Object *cmp2;
+
+ if (!IS_TYPE_POINTER_ONLY(type) || !IS_TYPE_FUNC(TYPE_POINTER(type)->target))
+ return CheckResult0;
+
+ used_obj = NULL;
+ type = TYPE_POINTER(type)->target;
+ found_non_template_func = 0;
+ is_ambig = 0;
+ for (; list; list = list->next) {
+ obj = OBJECT(list->object);
+ if (obj->otype != OT_OBJECT)
+ continue;
+
+ if (IS_TYPE_FUNC(obj->type) && (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_100000)) {
+ if (!found_non_template_func && CTempl_CanDeduceFunc(obj, TYPE_FUNC(type), templargs)) {
+ instance = CTempl_DeduceFunc(obj, TYPE_FUNC(type), templargs, NULL, 0);
+#line 1861
+ CError_ASSERT(instance);
+ if (is_typesame(instance->object->type, type)) {
+ if (used_obj && used_obj != instance->object)
+ is_ambig = 1;
+ else
+ used_obj = instance->object;
+ }
+ }
+ } else {
+ if (is_typesame(obj->type, type)) {
+ if (used_obj && found_non_template_func) {
+ cmp1 = obj;
+ if (obj->datatype == DALIAS)
+ cmp1 = obj->u.alias.object;
+ cmp2 = used_obj;
+ if (used_obj->datatype == DALIAS)
+ cmp2 = used_obj->u.alias.object;
+ if (cmp1 != cmp2)
+ is_ambig = 1;
+ } else {
+ is_ambig = 0;
+ used_obj = obj;
+ }
+ found_non_template_func = 1;
+ }
+ }
+ }
+
+ if (used_obj) {
+ if (flag1) {
+ if (is_ambig)
+ CError_Error(CErrorStr199);
+ expr = CExpr_MakeObjRefNode(used_obj, 1);
+ assign_node = expr;
+ expr->rtype = CDecl_NewPointerType(used_obj->type);
+ expr->flags = obj->qual & ENODE_FLAG_QUALS;
+ used_obj->flags |= OBJECT_FLAGS_UNUSED;
+ if (used_obj->datatype == DINLINEFUNC)
+ CError_Error(CErrorStr175);
+ }
+ return CheckResult1;
+ } else {
+ return CheckResult0;
+ }
}
ENode *CExpr_ConvertToBool(ENode *expr, Boolean flag) {
@@ -1702,7 +1811,225 @@ restart:
return NULL;
}
-void user_assign_check() {}
+short user_assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) {
+ Object *r26;
+ ENode *r25;
+ Boolean r24;
+ Boolean r23;
+ Boolean r22;
+ Type *r18b;
+ short r18;
+ TypeFunc *r17;
+ Object *r17b;
+ NameSpaceObjectList *r16b;
+ Object *r16;
+ Object *r15;
+ ENode *r15b;
+ ENode *r14;
+ short r14b;
+ TypeFunc *r14c;
+ ENodeList *r14d;
+ TypeMethod *r13;
+ ENodeList *r13b;
+ short result;
+ FuncArg *arg;
+ ConversionIterator iter;
+ Match5 stdmatch;
+ Match5 match_8C;
+ Match5 match_98;
+ BClassList path;
+ UInt16 chk;
+ Boolean is_const, is_volatile;
+
+#line 2378
+ CError_ASSERT(copts.old_argmatch);
+
+ memclrw(&stdmatch, sizeof(Match5));
+ r24 = 0;
+ r22 = 0;
+ r23 = 0;
+
+ if (!type->size)
+ CDecl_CompleteType(type);
+ if (!expr->rtype->size)
+ CDecl_CompleteType(expr->rtype);
+
+ if (IS_TYPE_CLASS(expr->rtype)) {
+ r18 = 0;
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype));
+ while ((r16 = CExpr_ConversionIteratorNext(&iter))) {
+ r17 = TYPE_FUNC(r16->type);
+ r14 = CExpr_NewENode(ETEMP);
+ r14->rtype = r17->functype;
+ if (IS_TYPE_REFERENCE(r14->rtype)) {
+ r14->rtype = TYPE_POINTER(r14->rtype)->target;
+ if (!CParser_IsConst(r14->rtype, r17->qual)) {
+ r14 = makemonadicnode(r14, EINDIRECT);
+ r14->data.monadic->rtype = TYPE(&void_ptr);
+ r14 = makemonadicnode(r14, EINDIRECT);
+ r14->data.monadic->rtype = TYPE(&void_ptr);
+ }
+ }
+ if ((result = std_assign_check(r14, type, 0, flag3))) {
+ CExpr_CalcStdAssign(result, &match_98, r17->functype, r17->qual, type, qual, 1);
+#line 2419
+ CError_ASSERT(r17->args && IS_TYPE_POINTER_ONLY(r17->args->type));
+ chk = expr->flags;
+ if (!(is_const = (r17->args->qual & Q_CONST)) && (chk & Q_CONST) != 0)
+ continue;
+ if (!(is_volatile = (r17->args->qual & Q_VOLATILE)) && (chk & Q_VOLATILE) != 0)
+ continue;
+ //if (((r17->args->qual & Q_CONST) == 0 && (chk & Q_CONST) != 0) || ((r17->args->qual & Q_VOLATILE) == 0 && (chk & Q_VOLATILE) != 0))
+ // continue;
+
+ r14b = 0;
+ if (is_const == (expr->flags & Q_CONST))
+ r14b++;
+ if (is_volatile == (expr->flags & Q_VOLATILE))
+ r14b++;
+ switch (CExpr_StdMatchCompare(&match_98, &stdmatch, 1)) {
+ case -1:
+ continue;
+ case 0:
+ if (r26 == r16)
+ continue;
+ if (r14b < r18)
+ continue;
+ if (r14b != r18)
+ break;
+ r22 = 1;
+ continue;
+ }
+ r26 = r16;
+ stdmatch = match_98;
+ r24 = 1;
+ r22 = 0;
+ r18 = r14b;
+ }
+ }
+ }
+
+ if (IS_TYPE_CLASS(type) && (r16b = CClass_Constructor(TYPE_CLASS(type)))) {
+ memclrw(&match_8C, sizeof(Match5));
+ for (; r16b; r16b = r16b->next) {
+ r17b = OBJECT(r16b->object);
+ if (r17b->otype != OT_OBJECT)
+ continue;
+ r14c = TYPE_FUNC(r17b->type);
+ if (!IS_TYPE_FUNC(r14c))
+ continue;
+ if (!flag2 && (r14c->qual & Q_EXPLICIT))
+ continue;
+ if (!r14c->args)
+ continue;
+ if (!(arg = r14c->args->next))
+ continue;
+ if ((TYPE_CLASS(type)->flags & CLASS_FLAGS_20) && !(arg = arg->next))
+ continue;
+ if (arg == &elipsis)
+ continue;
+ if (arg->next && !arg->next->dexpr && arg->next != &elipsis)
+ continue;
+
+ r18b = arg->type;
+ if (IS_TYPE_REFERENCE(r18b)) {
+ r18b = TYPE_POINTER(r18b)->target;
+ if (!CParser_IsConst(r18b, arg->qual) && !CExpr_IsLValue(expr))
+ continue;
+ }
+
+ if ((result = std_assign_check(expr, r18b, 0, flag3))) {
+ CExpr_CalcStdAssign(result, &match_98, r14c->functype, r14c->qual, type, qual, 0);
+ switch (CExpr_StdMatchCompare(&match_98, &match_8C, 1)) {
+ case -1:
+ case 0:
+ continue;
+ }
+ r25 = expr;
+ match_8C = match_98;
+ r23 = 1;
+ r15 = r17b;
+ }
+ }
+
+ if (r23) {
+ if (r24) {
+ switch (CExpr_StdMatchCompare(&stdmatch, &match_8C, 1)) {
+ case -1:
+ stdmatch = match_8C;
+ r24 = 0;
+ break;
+ case 0:
+ r22 = 1;
+ break;
+ }
+ } else {
+ stdmatch = match_8C;
+ }
+ }
+ }
+
+ if (r22 && flag1)
+ CError_Error(CErrorStr199);
+
+ if (r24 || r23) {
+ if (flag1) {
+ if (r24) {
+ r13 = TYPE_METHOD(r26->type);
+#line 2537
+ CError_ASSERT(r13->flags & FUNC_FLAGS_METHOD);
+ r15b = create_objectrefnode(r26);
+ r26->flags |= OBJECT_FLAGS_UNUSED;
+ r14d = lalloc(sizeof(ENodeList));
+ r14d->next = NULL;
+ expr = getnodeaddress(expr, 0);
+ r14d->node = CExpr_AssignmentPromotion(expr, CDecl_NewPointerType(TYPE(r13->theclass)), expr->flags, 0);
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->rtype = r13->functype;
+ expr->flags = r13->qual & ENODE_FLAG_QUALS;
+ expr->data.funccall.funcref = r15b;
+ expr->data.funccall.args = r14d;
+ expr->data.funccall.functype = TYPE_FUNC(r26->type);
+ assign_node = checkreference(CExpr_AdjustFunctionCall(expr));
+ if (assign_node->rtype != type)
+ assign_node = CExpr_AssignmentPromotion(assign_node, type, qual, 1);
+ if (!IS_TYPE_REFERENCE(r13->functype))
+ temp_reference_init = 1;
+ } else {
+ r13b = lalloc(sizeof(ENodeList));
+ r13b->next = NULL;
+ r13b->node = r25;
+ if (TYPE_CLASS(type)->flags & CLASS_FLAGS_20) {
+ r13b->next = lalloc(sizeof(ENodeList));
+ r13b->next->node = r25;
+ r13b->next->next = NULL;
+ r13b->node = intconstnode(TYPE(&stsignedshort), 1);
+ }
+ path.next = NULL;
+ path.type = type;
+ assign_node = makemonadicnode(create_temp_node(type), EINDIRECT);
+ assign_node->rtype = type;
+ assign_node = CExpr_GenericFuncCall(&path, assign_node, 0, r15, NULL, NULL, r13b, 0, 0, 1);
+ if (ENODE_IS2(assign_node, EFUNCCALL, EFUNCCALLP)) {
+ assign_node->rtype = CDecl_NewPointerType(type);
+ assign_node = makemonadicnode(assign_node, EINDIRECT);
+ assign_node->rtype = type;
+ }
+ temp_reference_init = 1;
+ }
+ }
+
+ user_std_match = stdmatch;
+ return CheckResult4;
+ } else {
+ if (flag1)
+ CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type, qual);
+ return CheckResult0;
+ }
+}
ENode *CExpr_ConvertToCondition(ENode *expr) {
switch (expr->rtype->type) {
@@ -1723,16 +2050,332 @@ ENode *CExpr_ConvertToCondition(ENode *expr) {
}
}
-void CExpr_ConvertToIntegral() {}
-void CExpr_CheckArithmConversion() {}
-void get_address_of_temp_copy() {}
+ENode *CExpr_ConvertToIntegral(ENode *expr) {
+ ConversionIterator iter;
+ Type *found;
+ Object *obj;
+
+ switch (expr->rtype->type) {
+ case TYPEINT:
+ case TYPEENUM:
+ return integralpromote(expr);
+ case TYPECLASS:
+ CDecl_CompleteType(expr->rtype);
+ found = NULL;
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (IS_TYPE_INT_OR_ENUM(TYPE_FUNC(obj->type)->functype)) {
+ if (found) {
+ CError_Error(CErrorStr199);
+ break;
+ }
+ found = TYPE_FUNC(obj->type)->functype;
+ }
+ }
+ if (found)
+ return integralpromote(CExpr_Convert(expr, found, 0, 0, 1));
+ break;
+ }
+
+ CError_Error(CErrorStr376, expr->rtype, expr->flags & ENODE_FLAG_QUALS);
+ return nullnode();
+}
+
+void CExpr_CheckArithmConversion(ENode *expr, Type *type) {
+ CInt64 val;
+
+ if (expr->rtype == type)
+ return;
+ if (expr->rtype == TYPE(&stbool))
+ return;
+
+ if (IS_TYPE_INT(expr->rtype)) {
+ if (IS_TYPE_FLOAT(type))
+ return;
+#line 2772
+ CError_ASSERT(IS_TYPE_INT(type));
+
+ if (type->size > expr->rtype->size)
+ return;
+ if (type->size == expr->rtype->size && is_unsigned(type) == is_unsigned(expr->rtype))
+ return;
+
+ switch (expr->type) {
+ case EINTCONST:
+ if (!CInt64_IsNegative(&expr->data.intval) || is_unsigned(expr->rtype) || !is_unsigned(type)) {
+ val = CExpr_IntConstConvert(type, expr->rtype, expr->data.intval);
+ val = CExpr_IntConstConvert(expr->rtype, type, val);
+ if (CInt64_Equal(val, expr->data.intval))
+ return;
+ }
+ break;
+ case ELOGNOT:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ return;
+ }
+ } else {
+ if (IS_TYPE_FLOAT(type) && type->size >= expr->rtype->size)
+ return;
+ }
+
+ CError_Warning(CErrorStr317, expr->rtype, 0, type, 0);
+}
+
+ENode *get_address_of_temp_copy(ENode *expr, Boolean flag) {
+ char buf[64];
+ ENode *result;
+ Object *obj;
+ Type *innertype;
+
+ if (flag) {
+ if (ENODE_IS2(expr, EINTCONST, EFLOATCONST)) {
+ obj = CParser_NewCompilerDefDataObject();
+ obj->type = expr->rtype;
+ obj->name = CParser_GetUniqueName();
+ obj->sclass = TK_STATIC;
+ if (ENODE_IS(expr, EINTCONST)) {
+ innertype = expr->rtype;
+ switch (innertype->type) {
+ case TYPEINT:
+ break;
+ case TYPEENUM:
+ innertype = TYPE_ENUM(innertype)->enumtype;
+ break;
+ case TYPEPOINTER:
+ innertype = TYPE(&stunsignedlong);
+ break;
+ default:
+#line 2857
+ CError_FATAL();
+ }
+ CMach_InitIntMem(innertype, expr->data.intval, buf);
+ } else {
+ CMach_InitFloatMem(expr->rtype, expr->data.floatval, buf);
+ }
+ CInit_DeclareData(obj, buf, NULL, obj->type->size);
+ return create_objectrefnode(obj);
+ }
+
+ if (cinit_tempnodefunc == NULL)
+ result = CExpr_NewETEMPNode(expr->rtype, 1);
+ else
+ result = cinit_tempnodefunc(expr->rtype, 0);
+ result = makemonadicnode(result, EINDIRECT);
+ result->rtype = TYPE_POINTER(result->rtype)->target;
+ return makecommaexpression(makediadicnode(result, expr, EASS), result->data.monadic);
+ } else {
+ result = nullnode();
+ CInt64_SetLong(&result->data.intval, -1);
+ result->rtype = CDecl_NewPointerType(expr->rtype);
+ return result;
+ }
+}
short assign_check(ENode *expr, Type *type, UInt32 qual, Boolean flag1, Boolean flag2, Boolean flag3) {
+ Type *type2;
+ Boolean r30;
+ Boolean r29;
+ short result;
+
+ assign_value = 1000;
+ r30 = 0;
+ r29 = 0;
+ temp_reference_init = 0;
+
+ type2 = type;
+ if (IS_TYPE_REFERENCE(type) && !IS_TYPE_FUNC(TYPE_POINTER(type)->target)) {
+ type2 = TYPE_POINTER(type)->target;
+ r30 = 1;
+ }
+
+ assign_node = expr;
+ if (IS_TYPE_ARRAY(type2)) {
+ r29 = 1;
+ type2 = CDecl_NewPointerType(TYPE_POINTER(type2)->target);
+ }
+
+ if (!type2->size) {
+ CDecl_CompleteType(type2);
+ if (!type2->size && !r30) {
+ if (flag1) {
+ if (IS_TYPE_CLASS(type2))
+ CError_Error(CErrorStr136, type2, 0);
+ else
+ CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual);
+ }
+ return CheckResult0;
+ }
+ }
+
+ if (copts.warn_implicitconv && flag1 && !flag2) {
+ if (IS_TYPE_INT_OR_FLOAT(type2) && IS_TYPE_INT_OR_FLOAT(expr->rtype))
+ CExpr_CheckArithmConversion(expr, type2);
+ }
+
+ result = std_assign_check(expr, type2, flag1, flag3);
+ if (!result) {
+ if (IS_TYPE_CLASS(expr->rtype) || IS_TYPE_CLASS(type2)) {
+ result = user_assign_check(expr, type2, qual, flag1, flag2, flag3);
+ } else if (flag1) {
+ CError_Error(CErrorStr244, expr->rtype, expr->flags & ENODE_FLAG_QUALS, type2, qual);
+ }
+ }
+
+ if (r30 && result) {
+ if (flag1) {
+ if (!ENODE_IS(assign_node, EINDIRECT)) {
+ if (!r29) {
+ assign_node = CExpr_LValue(assign_node, 0, 0);
+ if (!ENODE_IS(assign_node, EINDIRECT)) {
+ assign_node = get_address_of_temp_copy(assign_node, 1);
+ temp_reference_init = 1;
+ } else {
+ assign_node = getnodeaddress(assign_node, 0);
+ }
+ }
+ } else {
+ if (!CExpr_IsLValue(assign_node))
+ temp_reference_init = 1;
+ if (!r29)
+ assign_node = getnodeaddress(assign_node, 0);
+ }
+ } else {
+ if (!r29 && !CExpr_IsLValue(assign_node) && !CParser_IsConst(TYPE_POINTER(type)->target, qual)) {
+ result = CheckResult0;
+ }
+ }
+ }
+
+ return result;
+}
+
+Boolean CExpr_MatchCompare(Object *obj, Match13 *a, Match13 *b) {
+ Object *tmp;
+ ObjectList *list;
+
+ switch (CExpr_StdMatchCompare(&b->anotherm5, &a->anotherm5, 0)) {
+ case -1:
+ return 0;
+ case 0:
+ if (a->xE > b->xE)
+ return 0;
+ if (a->xE != b->xE)
+ break;
+ switch (CExpr_StdMatchCompare(&b->match5, &a->match5, 1)) {
+ case -1:
+ return 0;
+ case 0:
+ if (a->anotherm5.x8 > b->anotherm5.x8)
+ return 0;
+ if (a->anotherm5.x8 == b->anotherm5.x8 && (tmp = a->obj)) {
+ if (tmp->datatype == obj->datatype) {
+ add_it:
+ list = lalloc(sizeof(ObjectList));
+ list->next = a->list;
+ a->list = list;
+ list->object = obj;
+ return 0;
+ }
+ if (obj->datatype == DALIAS)
+ return 0;
+ if (tmp->datatype != DALIAS)
+ goto add_it;
+ }
+ }
+ }
+
+ *a = *b;
+ a->obj = obj;
+ return 1;
}
-void CExpr_MatchCompare() {}
-static void MatchOverloadFunc() {}
-void CExpr_GetFuncMatchArgs() {}
+static void MatchOverloadFunc(Object *obj, FuncArg *args, ENodeList *argexprs, Match13 *match) {
+ Match13 match2;
+
+ if (IS_TYPE_FUNC(obj->type) && !(TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_100000)) {
+ memclrw(&match2, sizeof(Match13));
+ while (1) {
+ if (!args || args->type == &stvoid) {
+ if (!argexprs)
+ break;
+ return;
+ }
+
+ if (args == &elipsis)
+ break;
+ if (args == &oldstyle)
+ break;
+
+ if (!argexprs) {
+ if (args->dexpr)
+ break;
+ return;
+ }
+
+ if (!CExpr_MatchAssign(args->type, args->qual, argexprs->node, &match2))
+ return;
+
+ argexprs = argexprs->next;
+ args = args->next;
+ }
+
+ CExpr_MatchCompare(obj, match, &match2);
+ }
+}
+
+Boolean CExpr_GetFuncMatchArgs(Object *obj, ENodeList *argexprs, ENode *expr, FuncMatchArgs *result) {
+ ENode *intexpr;
+
+ if (!(TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_METHOD)) {
+ result->exprs = argexprs;
+ result->args = TYPE_FUNC(obj->type)->args;
+ return 1;
+ }
+
+ if (TYPE_METHOD(obj->type)->x26) {
+ result->exprs = argexprs;
+ result->args = TYPE_FUNC(obj->type)->args;
+ return 1;
+ }
+
+ if (TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_1000) {
+ result->exprs = argexprs;
+ result->args = TYPE_FUNC(obj->type)->args->next;
+ return 1;
+ }
+
+ if (expr) {
+ intexpr = lalloc(sizeof(ENode));
+ intexpr->type = EINTCONST;
+ intexpr->cost = 0;
+ intexpr->flags = expr->flags;
+ intexpr->rtype = CDecl_NewPointerType(expr->rtype);
+ intexpr->data.intval = cint64_zero;
+
+ result->exprs = lalloc(sizeof(ENodeList));
+ result->exprs->next = argexprs;
+ result->exprs->node = intexpr;
+
+ if (obj->datatype == DALIAS) {
+ result->args = lalloc(sizeof(FuncArg));
+ *result->args = *TYPE_FUNC(obj->type)->args;
+ result->args->type = CDecl_NewPointerType(expr->rtype);
+ } else {
+ result->args = TYPE_FUNC(obj->type)->args;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *list) {
NameSpaceObjectList *first;
@@ -1753,7 +2396,45 @@ static NameSpaceObjectList *CExpr_CopyNameSpaceObjectList(NameSpaceObjectList *l
return first;
}
-static void CExpr_MatchArgList() {}
+static void CExpr_MatchArgList(NameSpaceObjectList *list, TemplArg *templargs, ENodeList *argexprs, Match13 *match, ENode *expr, Boolean flag) {
+ NameSpaceObjectList *copied_list;
+ NameSpaceObjectList *scan_list;
+ Object *obj;
+ ENodeList *scan_expr;
+ Boolean is_template;
+ FuncMatchArgs fma;
+
+ if (!copts.old_argmatch) {
+ CExpr_FuncArgMatch(CExpr_CopyNameSpaceObjectList(list), templargs, argexprs, match, expr, flag);
+ return;
+ }
+
+ copied_list = CExpr_CopyNameSpaceObjectList(list);
+
+ for (scan_expr = argexprs; scan_expr; scan_expr = scan_expr->next)
+ CDecl_CompleteType(scan_expr->node->rtype);
+
+ scan_list = copied_list;
+ is_template = 0;
+ for (; scan_list; scan_list = scan_list->next) {
+ obj = OBJECT(scan_list->object);
+ if (obj->otype != OT_OBJECT)
+ continue;
+ if (IS_TYPE_FUNC(obj->type) && (!flag || !(obj->qual & Q_EXPLICIT))) {
+ if (!(TYPE_FUNC(obj->type)->flags & FUNC_FLAGS_100000)) {
+ if (CExpr_GetFuncMatchArgs(obj, argexprs, expr, &fma))
+ MatchOverloadFunc(obj, fma.args, fma.exprs, match);
+ } else {
+ is_template = 1;
+ }
+ }
+ }
+
+ if (is_template) {
+ if (!match->obj || match->anotherm5.x2 || match->anotherm5.x4 || match->xE)
+ CTempl_FuncMatch(copied_list, templargs, argexprs, match, expr);
+ }
+}
ENode *CExpr_GetDefaultArgument(ENode *funcexpr, FuncArg *arg) {
ENode *tmp;
@@ -1860,24 +2541,870 @@ ENode *CExpr_VarArgPromotion(ENode *expr, Boolean flag) {
return expr;
}
-void CExpr_GenericFuncCall() {}
-void CExpr_GenericPtmfCall() {}
-static void CExpr_ConvertEMember() {}
-void CExpr_MakeFunctionCall() {}
-static void accept_conversion_type() {}
-static void CExpr_OperatorConversion() {}
-static void wild_conversion_check() {}
-static void monadic_conversion_check() {}
-static void is_legal_type_combination() {}
-static void match_class_type_conversion() {}
-static void match_type_class_conversion() {}
-static void match_class_class_conversion() {}
-void CExpr_CheckOperatorConversion() {}
-void CExpr_CheckOperator() {}
+ENode *CExpr_GenericFuncCall(BClassList *path, ENode *funcexpr, Boolean flag1, Object *obj, NameSpaceObjectList *nsol, TemplArg *templargs, ENodeList *nodes, Boolean flag2, Boolean flag3, Boolean flag4) {
+ TypeFunc *tfunc;
+ AccessType access;
+ FuncArg *scan_arg;
+ BClassList *buildpath;
+ ENode *objexpr;
+ ENodeList *scan_expr;
+ BClassList *pathcopy;
+ Boolean had_alias;
+ NameSpaceObjectList my_list;
+ Match13 match;
+
+ memclrw(&match, sizeof(Match13));
+
+ if (!obj || IS_TEMPL_FUNC(obj->type)) {
+ if (!funcexpr && cscope_currentfunc && cscope_currentclass && cscope_is_member_func) {
+ funcexpr = CClass_CreateThisSelfExpr();
+ if (funcexpr) {
+ funcexpr = makemonadicnode(funcexpr, EINDIRECT);
+ funcexpr->rtype = TYPE(cscope_currentclass);
+ }
+ }
+
+ if (obj) {
+ my_list.next = NULL;
+ my_list.object = OBJ_BASE(obj);
+ nsol = &my_list;
+ }
+
+ CExpr_MatchArgList(nsol, templargs, nodes, &match, funcexpr, flag2);
+ if (!match.obj) {
+ CError_ErrorFuncCall(CErrorStr248, nsol, nodes);
+ return nullnode();
+ }
+ if (match.list)
+ CError_OverloadedFunctionError(match.obj, match.list);
+ obj = match.obj;
+ }
+
+ objexpr = create_objectrefnode(obj);
+ tfunc = TYPE_FUNC(obj->type);
+ if (!IS_TYPE_FUNC(tfunc)) {
+ CError_Error(CErrorStr161);
+ return nullnode();
+ }
+
+ if (IS_TYPEFUNC_METHOD(tfunc) && !TYPE_METHOD(tfunc)->x26) {
+ had_alias = 0;
+ buildpath = NULL;
+ access = obj->access;
+ while (obj->datatype == DALIAS) {
+ buildpath = buildpath ? CClass_AppendPath(buildpath, CClass_GetPathCopy(obj->u.alias.member, 0)) : CClass_GetPathCopy(obj->u.alias.member, 0);
+ obj = obj->u.alias.object;
+ objexpr = create_objectrefnode(obj);
+ had_alias = 1;
+ }
+ if (flag3)
+ CError_Error(CErrorStr188);
+
+ if (TYPE_METHOD(tfunc)->theclass->sominfo && (!(obj->qual & Q_INLINE) || (obj->datatype == DVFUNC && !flag1))) {
+ pathcopy = CClass_GetPathCopy(path, 0);
+ funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4);
+ if (!funcexpr)
+ return nullnode();
+ objexpr = CSOM_MethodAccess(pathcopy, obj, flag1);
+ } else {
+ if (obj->datatype == DVFUNC) {
+ if (flag1 || (!copts._59 && !had_alias && funcexpr && CExpr_IsStaticType(funcexpr)))
+ objexpr->flags |= ENODE_FLAG_80;
+ }
+ funcexpr = CExpr_GetClassAccessNode(path, buildpath, funcexpr, obj, access, flag4);
+ if (!funcexpr)
+ return nullnode();
+ }
+
+ if (
+ (tfunc->flags & FUNC_FLAGS_8) &&
+ cscope_currentfunc &&
+ (TYPE_FUNC(cscope_currentfunc->type)->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)) &&
+ cscope_currentclass == TYPE_METHOD(tfunc)->theclass &&
+ ENODE_IS(funcexpr, EINDIRECT) &&
+ ENODE_IS(funcexpr->data.monadic, EINDIRECT) &&
+ ENODE_IS(funcexpr->data.monadic->data.monadic, EOBJREF) &&
+ funcexpr->data.monadic->data.monadic->data.objref->name == this_name_node &&
+ !(objexpr->flags & ENODE_FLAG_80)
+ )
+ CError_Warning(CErrorStr195);
+
+ scan_expr = lalloc(sizeof(ENodeList));
+ scan_expr->next = nodes;
+ scan_expr->node = funcexpr->data.monadic;
+ if (ENODE_IS(scan_expr->node, EOBJREF))
+ scan_expr->node->data.objref->flags |= OBJECT_FLAGS_2;
+
+ if (((funcexpr->flags & Q_CONST) && !(tfunc->args->qual & Q_CONST)) || ((funcexpr->flags & Q_VOLATILE) && !(tfunc->args->qual & Q_VOLATILE))) {
+ if (!(tfunc->flags & (FUNC_FLAGS_1000 | FUNC_FLAGS_2000)))
+ CError_Error(CErrorStr236);
+ }
+
+ nodes = scan_expr;
+ scan_expr = scan_expr->next;
+ scan_arg = tfunc->args->next;
+ } else {
+ if (flag4 && obj->access != ACCESSPROTECTED)
+ CClass_CheckObjectAccess(path, obj);
+
+ scan_arg = tfunc->args;
+ scan_expr = nodes;
+ if (tfunc->flags & FUNC_FLAGS_METHOD) {
+#line 3599
+ CError_ASSERT(TYPE_METHOD(tfunc)->theclass->sominfo == NULL);
+ }
+ }
+
+ while (scan_expr) {
+ if (scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) {
+ scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1);
+ scan_arg = scan_arg->next;
+ } else {
+ if (!scan_arg) {
+ my_list.next = NULL;
+ my_list.object = OBJ_BASE(obj);
+ CError_ErrorFuncCall(CErrorStr248, &my_list, nodes);
+ }
+ scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis);
+ }
+ scan_expr = scan_expr->next;
+ }
+
+ if (scan_arg) {
+ if (scan_arg != &elipsis && scan_arg != &oldstyle) {
+ if (!scan_arg->dexpr) {
+ my_list.next = NULL;
+ my_list.object = OBJ_BASE(obj);
+ CError_ErrorFuncCall(CErrorStr248, &my_list, nodes);
+ scan_arg = NULL;
+ }
+ } else {
+ scan_arg = NULL;
+ }
+ }
+
+ return CExpr_GenericCall(objexpr, nodes, tfunc, scan_arg);
+}
+
+ENode *CExpr_GenericPtmfCall(Object *obj, TypeFunc *tfunc, ENodeList *arg_exprs) {
+ ENodeList *scan_expr;
+ FuncArg *arg;
+
+ scan_expr = arg_exprs;
+ arg = tfunc->args;
+ while (scan_expr) {
+ if (!arg) {
+ CError_Error(CErrorStr162);
+ return nullnode();
+ }
+
+ if (arg != &elipsis && arg != &oldstyle) {
+ scan_expr->node = argumentpromotion(scan_expr->node, arg->type, arg->qual, 1);
+ arg = arg->next;
+ } else {
+ scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, arg == &elipsis);
+ }
+ scan_expr = scan_expr->next;
+ }
+
+ if (arg) {
+ if (arg != &elipsis && arg != &oldstyle) {
+ if (!arg->dexpr) {
+ CError_Error(CErrorStr162);
+ arg = NULL;
+ }
+ } else {
+ arg = NULL;
+ }
+ }
+
+ return CExpr_GenericCall(create_objectrefnode(obj), arg_exprs, tfunc, arg);
+}
+
+static ENode *CExpr_ConvertEMember(ENode *expr) {
+ ENode *result;
+
+ if (expr->data.emember->list->next || expr->data.emember->templargs) {
+ result = CExpr_NewENode(EOBJLIST);
+ result->rtype = OBJECT(expr->data.emember->list->object)->type;
+ result->data.objlist.list = expr->data.emember->list;
+ result->data.objlist.templargs = expr->data.emember->templargs;
+ return result;
+ }
+
+ if (expr->data.emember->list->object->otype != OT_OBJECT)
+ return NULL;
+ return CExpr_MakeObjRefNode(OBJECT(expr->data.emember->list->object), 1);
+}
+
+ENode *CExpr_MakeFunctionCall(ENode *funcexpr, ENodeList *arg_exprs) {
+ ENode *expr;
+ TypeFunc *tfunc;
+ BClassList *save_path;
+ ENode *save_expr;
+ Boolean save_1D;
+ Boolean save_isambig;
+
+ FuncArg *scan_arg;
+ ENodeList *scan_expr;
+ Boolean has_varargs;
+
+ if (ENODE_IS(funcexpr, EOBJLIST) && funcexpr->data.objlist.name) {
+ funcexpr->data.objlist.list = CScope_ArgumentDependentNameLookup(
+ funcexpr->data.objlist.list,
+ funcexpr->data.objlist.name,
+ arg_exprs, 0);
+ if (!funcexpr->data.objlist.list) {
+ CError_Error(CErrorStr140, CError_GetNameString(NULL, funcexpr->data.objlist.name));
+ return nullnode();
+ }
+
+ if (
+ funcexpr->data.objlist.list->object->otype == OT_OBJECT &&
+ (TYPE_FUNC(OBJECT(funcexpr->data.objlist.list->object)->type)->flags & FUNC_FLAGS_200) &&
+ (expr = CodeGen_HandleIntrinsicCall(OBJECT(funcexpr->data.objlist.list->object), arg_exprs)))
+ return expr;
+
+ return CExpr_GenericFuncCall(
+ NULL, NULL, 0, NULL,
+ funcexpr->data.objlist.list,
+ funcexpr->data.objlist.templargs,
+ arg_exprs, 0, 0, 1);
+ }
+
+ if (ENODE_IS(funcexpr, EMEMBER)) {
+ save_path = funcexpr->data.emember->path;
+ save_expr = funcexpr->data.emember->expr;
+ save_1D = funcexpr->data.emember->pr_1D;
+ save_isambig = funcexpr->data.emember->isambig;
+ funcexpr = CExpr_ConvertEMember(funcexpr);
+ if (!funcexpr) {
+ CError_Error(CErrorStr161);
+ return nullnode();
+ }
+ } else {
+ save_path = NULL;
+ save_expr = NULL;
+ save_1D = 0;
+ save_isambig = 0;
+ }
+
+ if (ENODE_IS(funcexpr, EOBJREF) && IS_TYPE_FUNC(funcexpr->data.objref->type) && (TYPE_FUNC(funcexpr->data.objref->type)->flags & FUNC_FLAGS_200)) {
+ if (!(expr = CodeGen_HandleIntrinsicCall(funcexpr->data.objref, arg_exprs))) {
+ expr = CExpr_GenericFuncCall(
+ save_path, save_expr, save_1D, funcexpr->data.objref,
+ NULL, NULL,
+ arg_exprs, 0, save_isambig, 1);
+ }
+ return expr;
+ }
+
+ if (ENODE_IS(funcexpr, EOBJLIST)) {
+ return CExpr_GenericFuncCall(
+ save_path, save_expr, save_1D, NULL,
+ funcexpr->data.objlist.list, funcexpr->data.objlist.templargs,
+ arg_exprs, 0, save_isambig, 1);
+ }
+
+ if (!IS_TYPE_POINTER_ONLY(funcexpr->rtype) || !IS_TYPE_FUNC((tfunc = TYPE_FUNC(TYPE_POINTER(funcexpr->rtype)->target)))) {
+ CError_Error(CErrorStr161);
+ return nullnode();
+ }
+
+ if (ENODE_IS(funcexpr, EOBJREF)) {
+ return CExpr_GenericFuncCall(
+ save_path, save_expr, save_1D, funcexpr->data.objref,
+ NULL, NULL, arg_exprs, 0, save_isambig, 1);
+ }
+
+ scan_expr = arg_exprs; // r25
+ scan_arg = tfunc->args; // r26
+ has_varargs = 0;
+ while (scan_expr) {
+ if (!has_varargs) {
+ if (!scan_arg) {
+ CError_Error(CErrorStr162);
+ return nullnode();
+ }
+ if (scan_arg == &elipsis || scan_arg == &oldstyle) {
+ scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, scan_arg == &elipsis);
+ has_varargs = 1;
+ } else {
+ scan_expr->node = argumentpromotion(scan_expr->node, scan_arg->type, scan_arg->qual, 1);
+ scan_arg = scan_arg->next;
+ }
+ } else {
+ scan_expr->node = CExpr_VarArgPromotion(scan_expr->node, 0);
+ }
+ scan_expr = scan_expr->next;
+ }
+
+ if (!has_varargs && scan_arg && scan_arg != &elipsis && scan_arg != &oldstyle) {
+ do {
+ if (!scan_arg->dexpr) {
+ CError_Error(CErrorStr162);
+ return nullnode();
+ }
+
+ if (arg_exprs) {
+ scan_expr = arg_exprs;
+ while (scan_expr->next)
+ scan_expr = scan_expr->next;
+ scan_expr->next = lalloc(sizeof(ENodeList));
+ scan_expr = scan_expr->next;
+ } else {
+ scan_expr = lalloc(sizeof(ENodeList));
+ arg_exprs = scan_expr;
+ }
+
+ scan_expr->next = NULL;
+ scan_expr->node = CExpr_GetDefaultArgument(funcexpr, scan_arg);
+ } while ((scan_arg = scan_arg->next) && scan_arg != &elipsis && scan_arg != &oldstyle);
+ }
+
+ expr = CExpr_NewENode(EFUNCCALL);
+ expr->cost = 4;
+ expr->rtype = tfunc->functype;
+ expr->flags = tfunc->qual & ENODE_FLAG_QUALS;
+ expr->data.funccall.funcref = funcexpr;
+ expr->data.funccall.args = arg_exprs;
+ expr->data.funccall.functype = tfunc;
+ return CExpr_AdjustFunctionCall(expr);
+}
+
+static Boolean accept_conversion_type(Type *type, short mode) {
+ switch (mode) {
+ case 0:
+ return IS_TYPE_INT(type);
+ case 1:
+ return IS_TYPE_INT_OR_FLOAT(type);
+ case 2:
+ return IS_TYPE_INT_OR_FLOAT(type) || IS_TYPE_POINTER_ONLY(type);
+ case 3:
+ return IS_TYPE_POINTER_ONLY(type);
+ default:
+#line 3912
+ CError_FATAL();
+ return 0;
+ }
+}
+
+static ENode *CExpr_OperatorConversion(ENode *expr, Type *type, UInt32 qual) {
+ if (IS_TYPE_CLASS(expr->rtype) && type) {
+ if (user_assign_check(expr, type, qual, 1, 0, 1))
+ return assign_node;
+ CError_Error(CErrorStr144);
+ }
+ return expr;
+}
+
+static Boolean wild_conversion_check(ENode *left, ENode *right, Conversion *conv) {
+ ConversionIterator iter;
+ Object *obj;
+
+ Type *check;
+ Type *left_type;
+ Type *right_type;
+
+ left_type = right_type = NULL;
+ if (IS_TYPE_CLASS(left->rtype)) {
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ check = TYPE_FUNC(obj->type)->functype;
+ if (accept_conversion_type(check, 2)) {
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2))
+ CError_Error(CErrorStr199);
+ }
+ left_type = check;
+ goto found_left;
+ }
+ }
+ return 0;
+ }
+found_left:
+ if (IS_TYPE_CLASS(right->rtype)) {
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ check = TYPE_FUNC(obj->type)->functype;
+ if (accept_conversion_type(check, 2)) {
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, 2))
+ CError_Error(CErrorStr199);
+ }
+ right_type = check;
+ goto found_right;
+ }
+ }
+ return 0;
+ }
+found_right:
+ conv->x0 = NULL;
+ conv->left = CExpr_OperatorConversion(left, left_type, 0);
+ conv->right = CExpr_OperatorConversion(right, right_type, 0);
+ return 1;
+}
+
+static Boolean monadic_conversion_check(ENode *expr, short which, Conversion *conv) {
+ ConversionIterator iter;
+ Object *obj;
+ Type *check;
+
+ if (!IS_TYPE_CLASS(expr->rtype))
+ return 0;
+
+ if (which == 4)
+ which = 2;
+ else if (which == 5)
+ which = 1;
+
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ check = TYPE_FUNC(obj->type)->functype;
+ if (accept_conversion_type(check, which)) {
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (accept_conversion_type(TYPE_FUNC(obj->type)->functype, which))
+ CError_Error(CErrorStr199);
+ }
+
+ conv->x0 = NULL;
+ conv->left = CExpr_OperatorConversion(expr, check, 0);
+ conv->right = NULL;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static Boolean is_legal_type_combination(Type *left, Type *right, short mode) {
+ int left_type;
+ int right_type;
+
+ if (IS_TYPE_ENUM(left))
+ left = TYPE_ENUM(left)->enumtype;
+ if (IS_TYPE_ENUM(right))
+ right = TYPE_ENUM(right)->enumtype;
+
+ if (IS_TYPE_REFERENCE(left))
+ left = TYPE_POINTER(left)->target;
+ if (IS_TYPE_REFERENCE(right))
+ right = TYPE_POINTER(right)->target;
+
+ left_type = left->type; // r7
+ right_type = right->type; // r8
+ switch (mode) {
+ case 3:
+ if (left_type != TYPEPOINTER || right_type != TYPEPOINTER)
+ return 0;
+ use_cpp_typeequal:
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return iscpp_typeequal(left, right);
+ case 7:
+ if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) {
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return 1;
+ }
+ return 0;
+ case 6:
+ if ((left_type == TYPEPOINTER && right_type == TYPEINT) || (left_type == TYPEINT && right_type == TYPEPOINTER)) {
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return 1;
+ }
+ case 2:
+ if (left_type == TYPEPOINTER || right_type == TYPEPOINTER)
+ goto use_cpp_typeequal;
+ case 1:
+ mode1:
+ if (left_type == TYPEFLOAT || right_type == TYPEFLOAT) {
+ if (left_type == TYPEFLOAT) {
+ if (right_type == TYPEFLOAT) {
+ if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral)
+ left = right;
+ diadic_arg2.type = left;
+ diadic_arg1.type = left;
+ return 1;
+ }
+ if (right_type != TYPEINT)
+ return 0;
+ diadic_arg2.type = left;
+ diadic_arg1.type = left;
+ return 1;
+ }
+ if (left_type != TYPEINT)
+ return 0;
+ diadic_arg2.type = right;
+ diadic_arg1.type = right;
+ return 1;
+ }
+ case 0:
+ if (left_type != TYPEINT || right_type != TYPEINT)
+ return 0;
+ if (TYPE_INTEGRAL(right)->integral > TYPE_INTEGRAL(left)->integral)
+ left = right;
+ if (TYPE_INTEGRAL(left)->integral < IT_INT)
+ left = TYPE(&stsignedint);
+ diadic_arg2.type = left;
+ diadic_arg1.type = left;
+ return 1;
+ case 4:
+ if (left_type == TYPEPOINTER) {
+ if (right_type != TYPEINT)
+ return 0;
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return 1;
+ }
+ if (right_type == TYPEPOINTER) {
+ if (left_type != TYPEINT)
+ return 0;
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return 1;
+ }
+ goto mode1;
+ case 5:
+ if (left_type != TYPEPOINTER)
+ goto mode1;
+ if (right_type == TYPEPOINTER)
+ goto use_cpp_typeequal;
+ if (right_type != TYPEINT)
+ return 0;
+ diadic_arg1.type = left;
+ diadic_arg2.type = right;
+ return 1;
+ default:
+#line 4132
+ CError_FATAL();
+ return 0;
+ }
+}
+
+static void match_class_type_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) {
+ ConversionIterator iter;
+ Object *obj;
+
+ if (which == 6) {
+ if (!ENODE_IS(right, EINTCONST) || !CInt64_IsZero(&right->data.intval) || !IS_TYPE_INT(right->rtype))
+ which = 2;
+ }
+
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(left->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (is_legal_type_combination(TYPE_FUNC(obj->type)->functype, right->rtype, which)) {
+ MatchOverloadFunc(obj, &diadic_arg1, list, match);
+ if (match->obj == obj) {
+ cexpr_left_conversion_type = diadic_arg1.type;
+ cexpr_right_conversion_type = diadic_arg2.type;
+ }
+ }
+ }
+}
+
+static void match_type_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) {
+ ConversionIterator iter;
+ Object *obj;
+
+ if (which == 6) {
+ if (!ENODE_IS(left, EINTCONST) || !CInt64_IsZero(&left->data.intval) || !IS_TYPE_INT(left->rtype))
+ which = 2;
+ }
+
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(right->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (is_legal_type_combination(left->rtype, TYPE_FUNC(obj->type)->functype, which)) {
+ MatchOverloadFunc(obj, &diadic_arg1, list, match);
+ if (match->obj == obj) {
+ cexpr_left_conversion_type = diadic_arg1.type;
+ cexpr_right_conversion_type = diadic_arg2.type;
+ }
+ }
+ }
+}
+
+static void match_class_class_conversion(Match13 *match, ENode *left, ENode *right, ENodeList *list, short which) {
+ ConversionIterator iter_left;
+ ConversionIterator iter_right;
+ Object *obj_left;
+ Object *obj_right;
+
+ if (which == 6)
+ which = 2;
+
+ CExpr_ConversionIteratorInit(&iter_left, TYPE_CLASS(left->rtype));
+ while ((obj_left = CExpr_ConversionIteratorNext(&iter_left))) {
+ CExpr_ConversionIteratorInit(&iter_right, TYPE_CLASS(right->rtype));
+ while ((obj_right = CExpr_ConversionIteratorNext(&iter_right))) {
+ if (is_legal_type_combination(TYPE_FUNC(obj_left->type)->functype, TYPE_FUNC(obj_right->type)->functype, which)) {
+ MatchOverloadFunc(obj_left, &diadic_arg1, list, match);
+ if (match->obj == obj_left) {
+ cexpr_left_conversion_type = diadic_arg1.type;
+ cexpr_right_conversion_type = diadic_arg2.type;
+ }
+ }
+ }
+ }
+}
+
+Boolean CExpr_CheckOperatorConversion(short token, ENode *left, ENode *right, ENodeList *list, Conversion *conv) {
+ Match13 match;
+ short which;
+
+ switch (token) {
+ case '*':
+ if (!right) {
+ which = 3;
+ break;
+ }
+ case '/':
+ which = 1;
+ break;
+ case '&':
+ if (!right)
+ return 0;
+ case '%':
+ case '^':
+ case '|':
+ case '~':
+ case TK_SHL:
+ case TK_SHR:
+ which = 0;
+ break;
+ case '[':
+ which = 7;
+ break;
+ case '+':
+ which = 4;
+ break;
+ case '-':
+ which = 5;
+ break;
+ case '!':
+ case ':':
+ case '<':
+ case '>':
+ case TK_LESS_EQUAL:
+ case TK_GREATER_EQUAL:
+ which = 2;
+ break;
+ case TK_LOGICAL_EQ:
+ case TK_LOGICAL_NE:
+ which = 6;
+ break;
+ case TK_LOGICAL_OR:
+ case TK_LOGICAL_AND:
+ return wild_conversion_check(left, right, conv);
+ default:
+ return 0;
+ }
+
+ if (!right)
+ return monadic_conversion_check(left, which, conv);
+
+ cexpr_left_conversion_type = cexpr_right_conversion_type = NULL;
+ memclrw(&match, sizeof(Match13));
+
+ if (IS_TYPE_CLASS(left->rtype)) {
+ if (IS_TYPE_CLASS(right->rtype))
+ match_class_class_conversion(&match, left, right, list, which);
+ else
+ match_class_type_conversion(&match, left, right, list, which);
+ } else {
+ if (IS_TYPE_CLASS(right->rtype))
+ match_type_class_conversion(&match, left, right, list, which);
+ else
+ return 0;
+ }
+
+ if (!match.obj)
+ return 0;
+ if (match.list)
+ CError_OverloadedFunctionError(match.obj, match.list);
+
+ conv->x0 = NULL;
+ conv->left = CExpr_OperatorConversion(left, cexpr_left_conversion_type, 0);
+ conv->right = CExpr_OperatorConversion(right, cexpr_right_conversion_type, 0);
+ return 1;
+}
+
+Boolean CExpr_CheckOperator(short token, ENode *left, ENode *right, Conversion *conv) {
+ Match13 match;
+ CScopeParseResult pr;
+ CScopeParseResult pr2;
+ ENode *expr;
+ Object *obj;
+ ENodeList *nodes;
+ HashNameNode *name;
+ BClassList *path;
+ EMemberInfo *member;
+ Object *prev_obj;
+ NameSpaceObjectList mylist_A8;
+ NameSpaceObjectList mylist_B0;
+
+ if (!copts.old_argmatch) {
+ if (token == '(') {
+ CDecl_CompleteType(left->rtype);
+ if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr,
+ CMangler_OperatorName(token))) {
+ if (pr.nsol_14 || (pr.obj_10 && pr.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr.obj_10)->type))) {
+ member = lalloc(sizeof(EMemberInfo));
+ memclrw(member, sizeof(EMemberInfo));
+ member->path = pr.bcl_18;
+ member->expr = left;
+ member->pr_1D = pr.x1D;
+ if (!pr.nsol_14) {
+ member->list = galloc(sizeof(NameSpaceObjectList));
+ member->list->next = NULL;
+ member->list->object = pr.obj_10;
+ } else {
+ member->list = pr.nsol_14;
+ }
+ expr = CExpr_NewENode(EMEMBER);
+ expr->rtype = &stvoid;
+ expr->data.emember = member;
+ tk = lex();
+ conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1)));
+ conv->left = NULL;
+ conv->right = NULL;
+ tk = lex();
+ return 1;
+ } else {
+#line 4371
+ CError_FATAL();
+ }
+ }
+ return 0;
+ } else {
+ return CExpr_OperatorMatch(token, left, right, conv);
+ }
+ }
+
+ if (!IS_TYPE_CLASS(left->rtype)) {
+ if (!IS_TYPE_ENUM(left->rtype)) {
+ if (!right)
+ return 0;
+ if (!IS_TYPE_CLASS(right->rtype) && !IS_TYPE_ENUM(right->rtype))
+ return 0;
+ }
+ } else {
+ CDecl_CompleteType(left->rtype);
+ }
+
+ memclrw(&match, sizeof(Match13));
+ name = CMangler_OperatorName(token);
+ if (token == '(') {
+ if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) {
+ if (pr2.nsol_14 || (pr2.obj_10 && pr2.obj_10->otype == OT_OBJECT && IS_TYPE_FUNC(OBJECT(pr2.obj_10)->type))) {
+ member = lalloc(sizeof(EMemberInfo));
+ memclrw(member, sizeof(EMemberInfo));
+ member->path = pr2.bcl_18;
+ member->expr = left;
+ member->pr_1D = pr2.x1D;
+ if (!pr2.nsol_14) {
+ member->list = galloc(sizeof(NameSpaceObjectList));
+ member->list->next = NULL;
+ member->list->object = pr2.obj_10;
+ } else {
+ member->list = pr2.nsol_14;
+ }
+ expr = CExpr_NewENode(EMEMBER);
+ expr->rtype = &stvoid;
+ expr->data.emember = member;
+ tk = lex();
+ conv->x0 = checkreference(CExpr_MakeFunctionCall(expr, CExpr_ScanExpressionList(1)));
+ conv->left = NULL;
+ conv->right = NULL;
+ tk = lex();
+ return 1;
+ } else {
+#line 4439
+ CError_FATAL();
+ }
+ }
+ return 0;
+ }
+
+ nodes = lalloc(sizeof(ENodeList));
+ nodes->node = left;
+ if (right) {
+ nodes->next = lalloc(sizeof(ENodeList));
+ nodes->next->node = right;
+ nodes->next->next = NULL;
+ } else {
+ nodes->next = NULL;
+ }
+
+ obj = NULL;
+ if (IS_TYPE_CLASS(left->rtype) && CScope_FindClassMemberObject(TYPE_CLASS(left->rtype), &pr2, name)) {
+ if (pr2.obj_10) {
+ mylist_B0.next = NULL;
+ mylist_B0.object = pr2.obj_10;
+ pr2.nsol_14 = &mylist_B0;
+ } else {
+#line 4470
+ CError_ASSERT(pr2.nsol_14);
+ }
+
+ if (token != '=' || (pr2.bcl_18->type == left->rtype && pr2.bcl_18->next == NULL)) {
+ prev_obj = match.obj;
+ CExpr_MatchArgList(pr2.nsol_14, NULL, nodes->next, &match, left, 0);
+ if (prev_obj != match.obj) {
+ obj = match.obj;
+ path = pr2.bcl_18;
+ }
+ }
+ }
+
+ if (CScope_FindNonClassObject(cscope_current, &pr2, name)) {
+ if (pr2.obj_10) {
+ mylist_A8.next = NULL;
+ mylist_A8.object = pr2.obj_10;
+ pr2.nsol_14 = &mylist_A8;
+ }
+ } else {
+ pr2.nsol_14 = NULL;
+ }
+
+ if (copts.arg_dep_lookup)
+ pr2.nsol_14 = CScope_ArgumentDependentNameLookup(pr2.nsol_14, name, nodes, 1);
+ if (pr2.nsol_14)
+ CExpr_MatchArgList(pr2.nsol_14, NULL, nodes, &match, NULL, 0);
+
+ if (!match.obj) {
+ if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype)))
+ return 0;
+ return CExpr_CheckOperatorConversion(token, left, right, nodes, conv);
+ }
+
+ if (!(token == '&' && !right) && (token != ',')) {
+ if (!IS_TYPE_CLASS(left->rtype) && (!right || !IS_TYPE_CLASS(right->rtype)) && match.xE)
+ return 0;
+ if (right && match.xE == 2 && CExpr_CheckOperatorConversion(token, left, right, nodes, conv))
+ return 1;
+ }
+
+ if (match.list)
+ CError_OverloadedFunctionError(match.obj, match.list);
+
+ if (match.obj == obj) {
+ conv->x0 = CExpr_GenericFuncCall(path, nodes->node, 0, match.obj, NULL, NULL, nodes->next, 0, 0, 1);
+ } else {
+ conv->x0 = CExpr_GenericFuncCall(NULL, NULL, 0, match.obj, NULL, NULL, nodes, 0, 0, 1);
+ }
+
+ conv->x0 = checkreference(conv->x0);
+ conv->left = NULL;
+ conv->right = NULL;
+ return 1;
+}
ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *args, Boolean flag1, Boolean flag2, Boolean flag3, Boolean flag4, Boolean flag5) {
ENode *expr;
- Object *ctor;
+ NameSpaceObjectList *ctorlist;
+ BClassList path;
#line 4595
CError_ASSERT(IS_TYPE_POINTER_ONLY(addr_expr->rtype));
@@ -1894,14 +3421,23 @@ ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *arg
return expr;
}
- if ((ctor = CClass_Constructor(tclass))) {
+ if ((ctorlist = CClass_Constructor(tclass))) {
if (tclass->flags & CLASS_FLAGS_20) {
ENodeList *list = lalloc(sizeof(ENodeList));
list->next = args;
args = list;
list->node = intconstnode(TYPE(&stsignedshort), flag2 != 0);
}
- // TODO: 12CE80 call to genericfunccall
+ path.next = NULL;
+ path.type = TYPE(tclass);
+ expr = CExpr_GenericFuncCall(&path, addr_expr, 0, NULL, ctorlist, NULL, args, !flag5, 0, flag4);
+ if (ENODE_IS2(expr, EFUNCCALL, EFUNCCALLP))
+ expr->rtype = CDecl_NewPointerType(TYPE(tclass));
+ if (flag1) {
+ expr = makemonadicnode(expr, EINDIRECT);
+ expr->rtype = TYPE(tclass);
+ }
+ return expr;
} else {
if (args) {
if (!args->next && ENODE_IS(addr_expr, EINDIRECT)) {
@@ -1916,19 +3452,796 @@ ENode *CExpr_ConstructObject(TypeClass *tclass, ENode *addr_expr, ENodeList *arg
}
}
-static void CExpr_DeleteFuncCall() {}
-static void CExpr_CopyPlacementNewArg() {}
-static void CExpr_PlacementDeleteCall() {}
-static void scan_type_name() {}
-static void cv_qualifier_list() {}
-static void scan_new_declarator() {}
-static void scan_new_type_name() {}
-static void CExpr_NewAlloc() {}
-static void CExpr_NewExceptionSafeAlloc() {}
-static void CExpr_NewExceptionSafeInit() {}
-static void CExpr_NewArray() {}
-static void CExpr_NewSimpleClass() {}
-static void CExpr_NewClass() {}
-void scannew() {}
-static void CExpr_DeleteArray() {}
-void scandelete() {}
+static ENode *CExpr_DeleteFuncCall(Object *obj, ENode *arg, Type *type, Boolean include_size) {
+ ENode *expr;
+ ENodeList *list;
+
+ expr = lalloc(sizeof(ENode));
+ expr->type = EFUNCCALL;
+ expr->cost = 4;
+ expr->flags = 0;
+ expr->rtype = &stvoid;
+ expr->data.funccall.funcref = create_objectrefnode(obj);
+ expr->data.funccall.functype = TYPE_FUNC(obj->type);
+ obj->flags |= OBJECT_FLAGS_UNUSED;
+
+ list = lalloc(sizeof(ENodeList));
+ list->node = arg;
+ expr->data.funccall.args = list;
+
+ if (include_size) {
+ list->next = lalloc(sizeof(ENodeList));
+ list->next->node = nullnode();
+ CInt64_SetLong(&list->next->node->data.intval, type->size);
+ list->next->node->rtype = CABI_GetSizeTType();
+ list->next->next = NULL;
+ } else {
+ list->next = NULL;
+ }
+
+ return expr;
+}
+
+static ENode *CExpr_CopyPlacementNewArg(ENodeList *list) {
+ switch (list->node->type) {
+ case EINDIRECT:
+ if (!ENODE_IS(list->node->data.monadic, EOBJREF))
+ break;
+ if (list->node->data.monadic->data.objref->datatype != DLOCAL && !is_const_object(list->node->data.monadic->data.objref))
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EOBJREF:
+ case EARGOBJ:
+ case ELOCOBJ:
+ case EOBJLIST:
+ case EVECTOR128CONST:
+ return CInline_CopyExpression(list->node, CopyMode0);
+ }
+
+ switch (list->node->rtype->type) {
+ default:
+#line 4726
+ CError_FATAL();
+ case TYPEINT:
+ case TYPEFLOAT:
+ case TYPEENUM:
+ case TYPESTRUCT:
+ case TYPECLASS:
+ case TYPEMEMBERPOINTER:
+ case TYPEPOINTER:
+ case TYPEOBJCID:
+ return CExpr_GetETEMPCopy(list->node);
+ }
+}
+
+static ENode *CExpr_PlacementDeleteCall(Type *type, ENode *expr, Object *obj, Boolean flag1, Boolean flag2) {
+ ENodeList *list;
+ Object *funcobj;
+ ENode *result;
+ ENodeList *inputarg;
+ Boolean outflag;
+
+#line 4752
+ CError_ASSERT(ENODE_IS(expr, EFUNCCALL) && ENODE_IS(expr->data.funccall.funcref, EOBJREF));
+
+ funcobj = expr->data.funccall.funcref->data.objref;
+#line 4756
+ CError_ASSERT(IS_TYPE_FUNC(funcobj->type) && TYPE_FUNC(funcobj->type)->args && TYPE_FUNC(funcobj->type)->args->next);
+
+ funcobj = CParser_FindDeallocationObject(type, TYPE_FUNC(funcobj->type)->args->next, flag1, flag2, &outflag);
+ if (!funcobj)
+ return NULL;
+
+ result = CExpr_NewENode(EFUNCCALL);
+ result->type = EFUNCCALL;
+ result->cost = 4;
+ result->rtype = &stvoid;
+ result->data.funccall.funcref = create_objectrefnode(funcobj);
+ result->data.funccall.functype = TYPE_FUNC(funcobj->type);
+ funcobj->flags |= OBJECT_FLAGS_UNUSED;
+
+ list = lalloc(sizeof(ENodeList));
+ list->node = create_objectnode(obj);
+ result->data.funccall.args = list;
+
+#line 4780
+ CError_ASSERT((inputarg = expr->data.funccall.args) && (inputarg = inputarg->next));
+
+ do {
+ list->next = lalloc(sizeof(ENodeList));
+ list = list->next;
+ list->node = CExpr_CopyPlacementNewArg(inputarg);
+ inputarg = inputarg->next;
+ } while (inputarg);
+ list->next = NULL;
+
+ return result;
+}
+
+static Type *scan_type_name(UInt32 *qual) {
+ DeclInfo di;
+ memclrw(&di, sizeof(DeclInfo));
+
+ CParser_GetDeclSpecs(&di, 0);
+ di.x46 = 1;
+ scandeclarator(&di);
+
+ if (di.name)
+ CError_Error(CErrorStr146);
+
+ firstarrayexpr = di.x24;
+ *qual = di.qual;
+ return di.thetype;
+}
+
+static UInt32 cv_qualifier_list(void) {
+ UInt32 qual;
+
+ qual = 0;
+ tk = lex();
+ while (tk >= TK_CONST && tk <= TK_ASM) {
+ switch (tk) {
+ case TK_CONST:
+ if (qual & Q_CONST)
+ CError_Error(CErrorStr121);
+ qual |= Q_CONST;
+ break;
+ case TK_VOLATILE:
+ if (qual & Q_VOLATILE)
+ CError_Error(CErrorStr121);
+ qual |= Q_VOLATILE;
+ break;
+ default:
+ CError_Error(CErrorStr121);
+ }
+
+ tk = lex();
+ }
+
+ return qual;
+}
+
+static void scan_new_declarator(DeclInfo *di, Boolean flag) {
+ CScopeParseResult pr;
+ SInt32 size;
+ ENode *expr;
+
+ switch (tk) {
+ case '*':
+ makethetypepointer(di, cv_qualifier_list());
+ if (tk != '[')
+ scan_new_declarator(di, flag);
+ break;
+ case TK_IDENTIFIER:
+ case TK_COLON_COLON:
+ if (CScope_ParseQualifiedNameSpace(&pr, 1, 0) && pr.nspace_0 && pr.nspace_0->theclass && tk == '*') {
+ makememberpointertype(di, pr.nspace_0->theclass, cv_qualifier_list());
+ if (tk != '[')
+ scan_new_declarator(di, flag);
+ } else {
+ CError_Error(CErrorStr121);
+ }
+ break;
+ }
+
+ if (tk == '[') {
+ tk = lex();
+ expr = expression();
+
+ if (IS_TYPE_ENUM(expr->rtype))
+ expr->rtype = TYPE_ENUM(expr->rtype)->enumtype;
+ if (!IS_TYPE_INT(expr->rtype))
+ CError_Error(CErrorStr146);
+
+ if (tk != ']')
+ CError_Error(CErrorStr125);
+ else
+ tk = lex();
+
+ if (tk == '[')
+ scan_new_declarator(di, 0);
+
+ if (CanCreateObject(di->thetype) && IsCompleteType(di->thetype)) {
+ di->thetype = CDecl_NewArrayType(di->thetype, 0);
+ if (!ENODE_IS(expr, EINTCONST)) {
+ size = 1;
+ if (!flag)
+ CError_Error(CErrorStr124);
+ else
+ firstarrayexpr = expr;
+ } else {
+ size = CInt64_GetULong(&expr->data.intval);
+ }
+ TYPE_POINTER(di->thetype)->size = size * TYPE_POINTER(di->thetype)->target->size;
+ } else {
+ CError_Error(CErrorStr129);
+ }
+ }
+}
+
+static Type *scan_new_type_name(UInt32 *qual) {
+ DeclInfo di;
+ memclrw(&di, sizeof(DeclInfo));
+
+ di.x4F = 1;
+ CParser_GetDeclSpecs(&di, 0);
+ scan_new_declarator(&di, 1);
+
+ *qual = di.qual;
+ return di.thetype;
+}
+
+static ENode *CExpr_NewAlloc(Type *type, ENodeList *args, Boolean flag1, Boolean flag2) {
+ NameSpaceObjectList *list;
+ Object *obj;
+ Boolean found;
+ HashNameNode *name;
+ CScopeParseResult pr;
+
+ found = 0;
+ if (!flag1 && IS_TYPE_CLASS(type)) {
+ list = NULL;
+ obj = NULL;
+ name = (flag2 && copts.array_new_delete) ? newa_fobj->name : newp_fobj->name;
+ if (CScope_FindClassMemberObject(TYPE_CLASS(type), &pr, name)) {
+ list = pr.nsol_14;
+ obj = OBJECT(pr.obj_10);
+#line 4935
+ CError_ASSERT(list || obj);
+ found = 1;
+ } else if (TYPE_CLASS(type)->flags & CLASS_FLAGS_1) {
+#line 4942
+ CError_ASSERT(!flag2);
+ obj = newh_func;
+ found = 1;
+ }
+ }
+
+ if (!found) {
+ if (flag2 && copts.array_new_delete)
+ list = &newa_fobj->first;
+ else
+ list = &newp_fobj->first;
+ obj = NULL;
+ }
+
+ return CExpr_GenericFuncCall(NULL, NULL, 0, obj, list, NULL, args, 0, 0, 1);
+}
+
+static ENode *CExpr_NewExceptionSafeAlloc(Type *type, ENode *node, ENodeList *args, Boolean flag1, Boolean flag2, Object **objptr) {
+ Object *obj;
+ ENode *result;
+ ENode *catchexpr;
+ Object *deletefunc;
+ Boolean include_size;
+
+ if (!cscope_currentfunc || !copts.delete_exception || !copts.exceptions)
+ return NULL;
+
+ obj = create_temp_object(TYPE(&void_ptr));
+ *objptr = obj;
+ deletefunc = NULL;
+ catchexpr = NULL;
+ include_size = 0;
+ if (args)
+ catchexpr = CExpr_PlacementDeleteCall(type, node, obj, flag1, flag2);
+ if (!args)
+ deletefunc = CParser_FindDeallocationObject(type, NULL, flag1, flag2, &include_size);
+
+ if (!deletefunc && !catchexpr)
+ return NULL;
+
+ result = lalloc(sizeof(ENode));
+ *result = *node;
+ node = makediadicnode(create_objectnode(obj), node, EASS);
+ if (!catchexpr && !include_size) {
+ result->type = ENEWEXCEPTION;
+ result->data.newexception.initexpr = node;
+ result->data.newexception.tryexpr = NULL;
+ result->data.newexception.pointertemp = obj;
+ result->data.newexception.deletefunc = deletefunc;
+ } else {
+ if (!catchexpr)
+ catchexpr = CExpr_DeleteFuncCall(deletefunc, create_objectnode(obj), type, include_size);
+ result->type = EMYSTERY67;
+ result->data.itc.initexpr = node;
+ result->data.itc.tryexpr = NULL;
+ result->data.itc.result = create_objectnode(obj);
+ result->data.itc.catchexpr = catchexpr;
+ }
+
+ return result;
+}
+
+static ENode *CExpr_NewExceptionSafeInit(ENode *expr, ENode *tryexpr) {
+ switch (expr->type) {
+ case ENEWEXCEPTION:
+ expr->data.newexception.tryexpr = tryexpr;
+ break;
+ case EMYSTERY67:
+ expr->data.itc.tryexpr = tryexpr;
+ break;
+ default:
+#line 5056
+ CError_FATAL();
+ }
+ return expr;
+}
+
+static ENode *CExpr_NewArray(Type *type, UInt32 qual, ENodeList *nodelist, Boolean flag) {
+ Type *tptr;
+ Type *sizetype;
+ Type *innertype;
+ ENodeList *newlist;
+ ENode *result;
+ Object *ctor;
+ Object *dtor;
+ ENode *ass;
+ ENode *etemp;
+ ENode *mul;
+ SInt32 count;
+ ENode *newalloc;
+ ENode *newESalloc;
+ Object *tempobj;
+ ENode *callexpr;
+
+ tptr = CDecl_NewPointerType(TYPE_POINTER(type)->target);
+ sizetype = CABI_GetSizeTType();
+ innertype = TYPE_POINTER(type)->target;
+ while (IS_TYPE_ARRAY(innertype))
+ innertype = TYPE_POINTER(innertype)->target;
+
+ if (!CanAllocObject(innertype) || !IsCompleteType(innertype))
+ return nullnode();
+
+ newlist = lalloc(sizeof(ENodeList));
+ newlist->next = nodelist;
+ if (tk == '(') {
+ tk = lex();
+ if (CExpr_ScanExpressionList(1))
+ CError_Error(CErrorStr174);
+ if (tk == ')')
+ tk = lex();
+ else
+ CError_Error(CErrorStr115);
+ }
+
+ if (!IS_TYPE_CLASS(innertype) || CClass_IsPODClass(TYPE_CLASS(innertype))) {
+ newlist->node = intconstnode(sizetype, type->size);
+ if (firstarrayexpr) {
+ newlist->node = makediadicnode(newlist->node, promote(firstarrayexpr, sizetype), EMUL);
+ optimizecomm(newlist->node);
+ }
+ result = CExpr_NewAlloc(innertype, newlist, flag, 1);
+ result->rtype = tptr;
+ result->flags |= (qual & ENODE_FLAG_QUALS);
+ return result;
+ }
+
+ ctor = NULL;
+ if (CClass_Constructor(TYPE_CLASS(innertype))) {
+ ctor = CClass_DefaultConstructor(TYPE_CLASS(innertype));
+ if (ctor) {
+ ctor->flags |= OBJECT_FLAGS_UNUSED;
+ } else {
+ ctor = CClass_DummyDefaultConstructor(TYPE_CLASS(innertype));
+ if (!ctor)
+ CError_Error(CErrorStr203);
+ }
+ }
+
+ dtor = CClass_Destructor(TYPE_CLASS(innertype));
+ if (dtor)
+ dtor = CABI_GetDestructorObject(dtor, 1);
+
+ ass = NULL;
+ if (firstarrayexpr) {
+ etemp = CExpr_NewETEMPNode(sizetype, 1);
+ mul = promote(firstarrayexpr, sizetype);
+ if (innertype->size)
+ count = type->size / innertype->size;
+ else
+ count = 0;
+ if (count > 1) {
+ mul = makediadicnode(mul, intconstnode(sizetype, count), EMUL);
+ optimizecomm(mul);
+ }
+ ass = makediadicnode(CExpr_DerefETEMPCopy(etemp), mul, EASS);
+ mul = makediadicnode(CExpr_DerefETEMPCopy(etemp), intconstnode(sizetype, innertype->size), EMUL);
+ optimizecomm(mul);
+ mul = makediadicnode(mul, intconstnode(sizetype, 16), EADD);
+ optimizecomm(mul);
+ newlist->node = mul;
+ etemp = CExpr_DerefETEMPCopy(etemp);
+ } else {
+ newlist->node = intconstnode(sizetype, type->size + 16);
+ if (innertype->size)
+ count = type->size / innertype->size;
+ else
+ count = 0;
+ etemp = intconstnode(sizetype, count);
+ }
+
+ newalloc = CExpr_NewAlloc(innertype, newlist, flag, 1);
+ newalloc->rtype = tptr;
+ newESalloc = CExpr_NewExceptionSafeAlloc(innertype, newalloc, nodelist, 1, flag, &tempobj);
+ if (newESalloc) {
+ callexpr = CExpr_FuncCallSix(
+ cnar_func,
+ create_objectnode(tempobj),
+ ctor ? create_objectrefnode(ctor) : nullnode(),
+ dtor ? create_objectrefnode(dtor) : nullnode(),
+ intconstnode(sizetype, innertype->size),
+ etemp,
+ NULL
+ );
+ result = CExpr_NewExceptionSafeInit(newESalloc, makediadicnode(create_objectnode(tempobj), callexpr, EASS));
+ } else {
+ result = CExpr_FuncCallSix(
+ cnar_func,
+ newalloc,
+ ctor ? create_objectrefnode(ctor) : nullnode(),
+ dtor ? create_objectrefnode(dtor) : nullnode(),
+ intconstnode(sizetype, innertype->size),
+ etemp,
+ NULL
+ );
+ }
+
+ if (ass)
+ result = makecommaexpression(ass, result);
+ result->rtype = tptr;
+ result->flags |= (qual & ENODE_FLAG_QUALS);
+ return result;
+}
+
+static ENode *CExpr_NewSimpleClass(TypeClass *tclass, ENode *expr, ENodeList *args) {
+ ENode *precomp;
+ ENode *nullcheck;
+
+ precomp = lalloc(sizeof(ENode));
+ *precomp = *expr;
+ precomp->type = EPRECOMP;
+ precomp->data.precompid = CParser_GetUniqueID();
+
+ nullcheck = lalloc(sizeof(ENode));
+ *nullcheck = *expr;
+ nullcheck->type = ENULLCHECK;
+ nullcheck->cost = 4;
+ nullcheck->data.nullcheck.nullcheckexpr = expr;
+ nullcheck->data.nullcheck.condexpr = CExpr_ConstructObject(tclass, precomp, args, 0, 1, 1, 1, 1);
+ nullcheck->data.nullcheck.precompid = precomp->data.precompid;
+ return nullcheck;
+}
+
+static ENode *CExpr_NewClass(TypeClass *tclass, ENode *expr, ENodeList *args1, ENodeList *args2, Boolean flag) {
+ Object *objptr;
+ ENode *newESalloc;
+
+ if (!args2 && !flag && CABI_ConstructorCallsNew(tclass)) {
+ expr = nullnode();
+ expr->rtype = CDecl_NewPointerType(TYPE(tclass));
+ return CExpr_ConstructObject(tclass, expr, args1, 0, 1, 1, 1, 1);
+ } else {
+ newESalloc = CExpr_NewExceptionSafeAlloc(TYPE(tclass), expr, args2, 0, flag, &objptr);
+ if (newESalloc) {
+ return CExpr_NewExceptionSafeInit(
+ newESalloc,
+ CExpr_ConstructObject(tclass, create_objectnode(objptr), args1, 0, 1, 1, 1, 1));
+ } else {
+ return CExpr_NewSimpleClass(tclass, expr, args1);
+ }
+ }
+}
+
+ENode *scannew(Boolean flag) {
+ Type *type; // r27
+ UInt32 qual;
+ ENodeList *args; // r28
+ Boolean placement_flag; // r26
+ ENodeList *newargs; // r26
+ ENode *expr; // r26
+ ENodeList *args2; // r29
+ Object *tempobj;
+ ENode *newESalloc; // r28
+ ENode *tempobj_expr; // r25
+ ENode *etemp_expr; // r28
+ ENode *indirect_expr; // r25
+ ENode *ass; // r25
+ ENode *cond; // r27
+
+ type = NULL;
+ args = NULL;
+ firstarrayexpr = NULL;
+ if ((tk = lex()) == '(') {
+ tk = lex();
+ placement_flag = isdeclaration(1, 1, 1, ')');
+ if (!placement_flag)
+ args = CExpr_ScanExpressionList(1);
+ if (placement_flag)
+ type = scan_type_name(&qual);
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ else
+ tk = lex();
+ }
+
+ if (!type) {
+ if (tk == '(') {
+ tk = lex();
+ type = scan_type_name(&qual);
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ else
+ tk = lex();
+ } else {
+ type = scan_new_type_name(&qual);
+ }
+ }
+
+ if (IS_TYPE_ARRAY(type))
+ return CExpr_NewArray(type, qual, args, flag);
+
+ if (IS_TYPE_CLASS(type)) {
+ if (TYPE_CLASS(type)->sominfo)
+ return CSOM_New(TYPE_CLASS(type));
+ if (TYPE_CLASS(type)->objcinfo)
+ return CObjC_New(TYPE_CLASS(type));
+ }
+
+ if (!IsCompleteType(type) || !CanAllocObject(type))
+ return nullnode();
+
+ newargs = lalloc(sizeof(ENodeList));
+ newargs->next = args;
+ newargs->node = intconstnode(CABI_GetSizeTType(), type->size);
+
+ expr = CExpr_NewAlloc(type, newargs, flag, 0);
+ expr->rtype = CDecl_NewPointerType(type);
+ expr->flags |= (qual & ENODE_FLAG_QUALS);
+
+ if (tk == '(') {
+ tk = lex();
+ args2 = CExpr_ScanExpressionList(1);
+ if (!args2 && !IS_TYPE_CLASS(type)) {
+ args2 = lalloc(sizeof(ENodeList));
+ memclrw(args2, sizeof(ENodeList));
+ args2->node = do_typecast(nullnode(), type, 0);
+ }
+ if (tk == ')')
+ tk = lex();
+ else
+ CError_Error(CErrorStr115);
+ } else {
+ args2 = NULL;
+ }
+
+ if (ENODE_IS(expr, EINTCONST))
+ return expr;
+
+ if (IS_TYPE_CLASS(type) && CClass_Constructor(TYPE_CLASS(type)))
+ return CExpr_NewClass(TYPE_CLASS(type), expr, args2, args, flag);
+
+ if (args2) {
+ if (args2->next) {
+ CError_Error(CErrorStr174);
+ return nullnode();
+ }
+
+ newESalloc = CExpr_NewExceptionSafeAlloc(type, expr, args, 0, flag, &tempobj);
+ if (newESalloc) {
+ tempobj_expr = makemonadicnode(create_objectnode(tempobj), EINDIRECT);
+ tempobj_expr->rtype = type;
+ tempobj_expr->flags = args2->node->flags & ENODE_FLAG_QUALS;
+ return CExpr_NewExceptionSafeInit(
+ newESalloc,
+ makediadicnode(tempobj_expr, CExpr_AssignmentPromotion(args2->node, type, newESalloc->flags, 1), EASS)
+ );
+ } else {
+ etemp_expr = CExpr_GetETEMPCopy(expr);
+ indirect_expr = makemonadicnode(etemp_expr, EINDIRECT);
+ indirect_expr->rtype = type;
+ indirect_expr->flags = args2->node->flags & ENODE_FLAG_QUALS;
+ ass = makediadicnode(indirect_expr, CExpr_AssignmentPromotion(args2->node, type, indirect_expr->flags, 1), EASS);
+ cond = CExpr_NewENode(ECOND);
+ cond->cost = 4;
+ cond->rtype = &stvoid;
+ cond->data.cond.cond = expr;
+ cond->data.cond.expr1 = ass;
+ cond->data.cond.expr2 = nullnode();
+ cond = makecommaexpression(cond, etemp_expr);
+ cond->rtype = etemp_expr->rtype;
+ cond->flags = etemp_expr->flags;
+ return cond;
+ }
+ } else {
+ return expr;
+ }
+}
+
+static ENode *CExpr_DeleteArray(ENode *expr, Type *type, Boolean flag) {
+ Object *obj;
+ Object *dtor;
+ Boolean outflag;
+ ENode *precomp;
+ SInt32 precompid;
+ ENode *tmp;
+ ENode *result;
+
+ obj = CParser_FindDeallocationObject(type, NULL, 1, flag, &outflag);
+
+ if (!IS_TYPE_CLASS(type) || CClass_IsPODClass(TYPE_CLASS(type)))
+ return CExpr_DeleteFuncCall(obj, expr, type, outflag);
+
+ dtor = CClass_Destructor(TYPE_CLASS(type));
+ if (dtor || outflag) {
+ if (obj->nspace == cscope_root && !outflag) {
+ return funccallexpr(dnar_func, expr, dtor ? create_objectrefnode(dtor) : nullnode(), NULL, NULL);
+ }
+ return funccallexpr(
+ dnar3_func,
+ expr,
+ dtor ? create_objectrefnode(dtor) : nullnode(),
+ create_objectrefnode(obj),
+ intconstnode(TYPE(&stsignedshort), outflag));
+ }
+
+ precomp = lalloc(sizeof(ENode));
+ *precomp = *expr;
+ precomp->type = EPRECOMP;
+ precomp->data.precompid = precompid = CParser_GetUniqueID();
+ tmp = CExpr_DeleteFuncCall(obj, makediadicnode(precomp, intconstnode(CABI_GetSizeTType(), 16), ESUB), type, 0);
+
+ result = CExpr_NewENode(ENULLCHECK);
+ result->rtype = &stvoid;
+ result->cost = 4;
+ result->data.nullcheck.nullcheckexpr = expr;
+ result->data.nullcheck.condexpr = tmp;
+ result->data.nullcheck.precompid = precompid;
+
+ return result;
+}
+
+ENode *scandelete(Boolean flag) {
+ Boolean is_array; // r24
+ ENode *expr; // r25
+ Type *conv_type; // r22
+ UInt32 conv_qual; // r23
+ Type *innertype; // r23
+ Type *t;
+ Object *obj;
+ Object *dtor; // r24
+ ENode *result_expr; // r24???
+ ENode *precomp_orig; // r31
+ SInt32 precompid; // r30
+ Boolean is_virtual; // r23
+ ENode *nc;
+ ConversionIterator iter;
+ Boolean outflag;
+ BClassList path;
+
+ if ((tk = lex()) == '[') {
+ if ((tk = lex()) != ']')
+ CError_Error(CErrorStr125);
+ else
+ tk = lex();
+ is_array = 1;
+ } else {
+ is_array = 0;
+ }
+
+ expr = cast_expression();
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ if (IS_TYPE_CLASS(expr->rtype)) {
+ conv_type = NULL;
+ CExpr_ConversionIteratorInit(&iter, TYPE_CLASS(expr->rtype));
+ while ((obj = CExpr_ConversionIteratorNext(&iter))) {
+ if (IS_TYPE_POINTER_ONLY(TYPE_FUNC(obj->type)->functype)) {
+ if (conv_type) {
+ CError_Error(CErrorStr199);
+ break;
+ }
+ conv_type = TYPE_FUNC(obj->type)->functype;
+ conv_qual = TYPE_FUNC(obj->type)->qual;
+ }
+ }
+ if (conv_type) {
+ if (!copts.old_argmatch) {
+ expr = CExpr_Convert(expr, conv_type, conv_qual, 1, 1);
+ } else {
+ if (user_assign_check(expr, conv_type, conv_qual, 1, 0, 1))
+ expr = assign_node;
+ }
+ }
+ }
+ if (!IS_TYPE_POINTER_ONLY(expr->rtype)) {
+ CError_Error(CErrorStr146);
+ return nullnode();
+ }
+ }
+
+ innertype = TYPE_POINTER(expr->rtype)->target;
+ if (innertype->size == 0)
+ CDecl_CompleteType(innertype);
+
+ if (IS_TYPE_ARRAY(innertype) && !is_array)
+ CError_Error(CErrorStr146);
+
+ if (is_array) {
+ t = innertype;
+ while (IS_TYPE_ARRAY(t))
+ t = TYPE_POINTER(t)->target;
+ return CExpr_DeleteArray(expr, t, flag);
+ }
+
+ if (copts.objective_c && CObjC_IsType_id(expr->rtype))
+ return CObjC_Delete(NULL, expr);
+
+ if (!IS_TYPE_CLASS(innertype)) {
+ obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag);
+ CClass_CheckObjectAccess(NULL, obj);
+ return CExpr_DeleteFuncCall(obj, expr, innertype, outflag);
+ }
+
+ if (TYPE_CLASS(innertype)->sominfo)
+ return CSOM_Delete(TYPE_CLASS(innertype), expr);
+
+ if (TYPE_CLASS(innertype)->objcinfo)
+ return CObjC_Delete(TYPE_CLASS(innertype), expr);
+
+ if (!(TYPE_CLASS(innertype)->flags & CLASS_FLAGS_2) && copts.pedantic)
+ CError_Warning(CErrorStr136, innertype, 0);
+
+ obj = CParser_FindDeallocationObject(innertype, NULL, 0, flag, &outflag);
+ CClass_CheckObjectAccess(NULL, obj);
+ dtor = CClass_Destructor(TYPE_CLASS(innertype));
+ if (!dtor)
+ return CExpr_DeleteFuncCall(obj, expr, innertype, outflag);
+
+ path.next = NULL;
+ path.type = innertype;
+ CClass_CheckObjectAccess(&path, dtor);
+
+ result_expr = lalloc(sizeof(ENode));
+ result_expr->type = EFUNCCALL;
+ result_expr->cost = 4;
+ result_expr->flags = 0;
+ result_expr->rtype = &stvoid;
+ if (dtor->datatype == DVFUNC) {
+ precomp_orig = expr;
+ expr = lalloc(sizeof(ENode));
+ *expr = *precomp_orig;
+ expr->type = EPRECOMP;
+ expr->data.precompid = precompid = CParser_GetUniqueID();
+ is_virtual = 1;
+ } else {
+ is_virtual = 0;
+ }
+
+ if (!flag) {
+ result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 1);
+ } else {
+#line 5650
+ CError_ASSERT(!outflag);
+ result_expr = CABI_DestroyObject(dtor, expr, 2, 0, 0);
+ result_expr->rtype = TYPE(&void_ptr);
+ result_expr = funccallexpr(obj, result_expr, NULL, NULL, NULL);
+ obj->flags |= OBJECT_FLAGS_UNUSED;
+ }
+
+ if (is_virtual) {
+ nc = lalloc(sizeof(ENode));
+ nc->type = ENULLCHECK;
+ nc->rtype = &stvoid;
+ nc->cost = 4;
+ nc->flags = 0;
+ nc->data.nullcheck.nullcheckexpr = precomp_orig;
+ nc->data.nullcheck.condexpr = result_expr;
+ nc->data.nullcheck.precompid = precompid;
+ return nc;
+ } else {
+ return result_expr;
+ }
+}
diff --git a/compiler_and_linker/unsorted/CIRTransform.c b/compiler_and_linker/unsorted/CIRTransform.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CIRTransform.c
diff --git a/compiler_and_linker/unsorted/CInline.c b/compiler_and_linker/unsorted/CInline.c
index bd2e46c..1f11b61 100644
--- a/compiler_and_linker/unsorted/CInline.c
+++ b/compiler_and_linker/unsorted/CInline.c
@@ -84,7 +84,7 @@ static void CInline_ForceReverseSearch(ENode *) {}
static ENode *CInline_ForceReverseEvaluation(ENode *expr) {}
static void CInline_ExportCheck(ENode *expr) {}
static void CInline_Expand(Statement *stmt) {}
-SInt32 CInline_GetStatementNumber(Statement *first, Statement *stmt) {}
+SInt16 CInline_GetStatementNumber(Statement *first, Statement *stmt) {}
static CI_Switch *CInline_PackSwitch(Statement *s1, Statement *s2) {}
static Boolean CInline_CanInline(Object *obj, Statement *stmt) {}
static ExceptionAction *CInline_PackActions(Statement *s1, Statement *s2) {}
diff --git a/compiler_and_linker/unsorted/CMachine.c b/compiler_and_linker/unsorted/CMachine.c
index fd4aafc..0c1ac0d 100644
--- a/compiler_and_linker/unsorted/CMachine.c
+++ b/compiler_and_linker/unsorted/CMachine.c
@@ -1337,7 +1337,7 @@ Boolean CMach_PassResultInHiddenArg(Type *type) {
}
}
-const char *CMach_GetCPU() {
+char *CMach_GetCPU() {
switch (copts.cpu) {
case CPU_PPC401: return "__PPC401__";
case CPU_PPC403: return "__PPC403__";
diff --git a/compiler_and_linker/unsorted/CObjC.c b/compiler_and_linker/unsorted/CObjC.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CObjC.c
diff --git a/compiler_and_linker/unsorted/CObjCModern.c b/compiler_and_linker/unsorted/CObjCModern.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CObjCModern.c
diff --git a/compiler_and_linker/unsorted/COptimizer.c b/compiler_and_linker/unsorted/COptimizer.c
new file mode 100644
index 0000000..38b203f
--- /dev/null
+++ b/compiler_and_linker/unsorted/COptimizer.c
@@ -0,0 +1,1781 @@
+#include "compiler/COptimizer.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CClass.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/CParser.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/CodeGen.h"
+#include "compiler/Switch.h"
+#include "compiler/Exceptions.h"
+#include "compiler/IrOptimizer.h"
+#include "cos.h"
+
+COptBlock *basicblocks;
+Boolean copt_isleaffunction;
+static Boolean stmtchanged;
+static COptBlock *currentblock;
+static ENode *mexpr;
+static short setbytes;
+static COptCSE *csenodes[MAXEXPR];
+static COptCSEList *cselist;
+static short extravars;
+static Boolean cse_found;
+static Boolean cse_invals;
+static Boolean static_for_inlines;
+static short replaces;
+static ENode *objrefnode;
+static int objrefnodes;
+
+static short bitmasks[] = {
+ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
+ 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000
+};
+
+// forward decls
+static COptCSE *cse_expression(ENode *expr);
+
+static COptCSE *cse_new(ENode *expr) {
+ COptCSE *cse = oalloc(sizeof(COptCSE));
+ cse->expr = expr;
+ cse->replaced = NULL;
+ cse->block = currentblock;
+ cse->mexpr = mexpr;
+ cse->left = NULL;
+ cse->right = NULL;
+ cse->x1C = 1;
+ return cse;
+}
+
+static COptCSE *cse_append(COptCSE *cse, ENode *expr) {
+ COptCSEList *list = oalloc(sizeof(COptCSEList));
+ list->next = cselist;
+ cselist = list;
+ list->cse = cse;
+ list->expr = expr;
+ return cse;
+}
+
+static void cse_cleanup(void) {
+ COptCSEList *scanlist;
+ COptCSEList *prevlist;
+ COptCSE *scan;
+ COptCSE *prev;
+ short op;
+
+ scanlist = cselist;
+ while (scanlist && !scanlist->cse)
+ scanlist = scanlist->next;
+ cselist = scanlist;
+
+ if (scanlist) {
+ do {
+ prevlist = scanlist;
+ do {
+ scanlist = scanlist->next;
+ } while (scanlist && !scanlist->cse);
+ prevlist->next = scanlist;
+ } while (scanlist);
+ }
+
+ for (op = 0; op < MAXEXPR; op++) {
+ scan = csenodes[op];
+ while (scan && scan->x1C < 0)
+ scan = scan->next;
+ csenodes[op] = scan;
+
+ if (scan) {
+ do {
+ prev = scan;
+ do {
+ scan = scan->next;
+ } while (scan && scan->x1C < 0);
+ prev->next = scan;
+ } while (scan);
+ }
+ }
+}
+
+static void cse_inval(COptCSE *cse) {
+ COptCSEList *scanlist;
+ COptCSE *scan;
+ short op;
+
+ if (cse) {
+ for (scanlist = cselist; scanlist; scanlist = scanlist->next) {
+ if (scanlist->cse == cse) {
+ scanlist->cse = NULL;
+ scanlist->expr = NULL;
+ }
+ }
+
+ cse->x1C = -1;
+ cse->left = NULL;
+ cse->right = NULL;
+
+ for (op = 0; op < MAXEXPR; op++) {
+ for (scan = csenodes[op]; scan; scan = scan->next) {
+ if (scan->left == cse || scan->right == cse)
+ cse_inval(scan);
+ }
+ }
+ }
+}
+
+static void cse_update_usages(COptCSE *cse, short amount) {
+ cse->x1C /= amount;
+ if (cse->left)
+ cse_update_usages(cse->left, amount);
+ if (cse->right)
+ cse_update_usages(cse->right, amount);
+}
+
+static void cse_replace(ENode *expr, COptCSE *cse) {
+ COptCSEList *list;
+
+ for (list = cselist; list; list = list->next) {
+ if (list->cse == cse) {
+ *list->expr = *expr;
+ replaces++;
+ list->cse = NULL;
+ list->expr = NULL;
+ }
+ }
+}
+
+static short cse_objectcost(Object *obj) {
+ if (obj->datatype == DLOCAL && !obj->u.var.info->noregister)
+ return 0;
+ return 1;
+}
+
+static void cse_treereplacemexpr(COptCSE *cse, ENode *from, ENode *to) {
+ if (cse->mexpr == from)
+ cse->mexpr = to;
+ if (cse->left)
+ cse_treereplacemexpr(cse->left, from, to);
+ if (cse->right)
+ cse_treereplacemexpr(cse->right, from, to);
+}
+
+static Boolean cse_issubcse(COptCSE *a, COptCSE *b) {
+ if (a == b)
+ return 1;
+ if (b->left && cse_issubcse(a, b->left))
+ return 1;
+ if (b->right && cse_issubcse(a, b->right))
+ return 1;
+
+ return 0;
+}
+
+static short cse_cost(COptCSE *cse) {
+ short cost;
+
+ if (cse) {
+ while (ENODE_IS(cse->expr, ETYPCON) && cse->expr->rtype->type == cse->expr->data.monadic->rtype->type && cse->expr->rtype->size == cse->expr->data.monadic->rtype->size)
+ cse = cse->left;
+
+ if (ENODE_IS_INDIRECT_TO(cse->expr, EOBJREF))
+ return cse_objectcost(cse->expr->data.monadic->data.objref);
+
+ cost = 1;
+ if (!copts.optimize_for_size) {
+ if (ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO))
+ cost = 2;
+ }
+ //cost = (!copts.optimize_for_size && ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) ? 2 : 1;
+ return cse_cost(cse->left) + cse_cost(cse->right) + cost;
+ //return
+ // ((!copts.optimize_for_size && ENODE_IS3(cse->expr, EMUL, EDIV, EMODULO)) ? 2 : 1) +
+ // cse_cost(cse->left) +
+ // cse_cost(cse->right);
+ }
+
+ return 0;
+}
+
+static void cse_remove(void) {
+ short op; // r27
+ COptCSE *cse; // r25
+ COptCSE *best_cse; // r28
+ int best_cost; // r30
+ Object *obj; // r31
+ Boolean did_replacement; // r24
+ VarInfo *vi; // r27
+ ObjectList *objlist;
+ ENode *expr1;
+ ENode *expr2;
+ ENode *expr3;
+ ENode *expr4;
+ ENode *mexprsave;
+ COptCSEList *list;
+ short cost;
+
+ while (1) {
+ op = 0;
+ best_cse = NULL;
+ best_cost = 0;
+ did_replacement = 0;
+
+ for (; op < MAXEXPR; op++) {
+ switch (op) {
+ case EINTCONST:
+ case EFLOATCONST:
+ case EOBJREF:
+ case EVECTOR128CONST:
+ break;
+ default:
+ for (cse = csenodes[op]; cse; cse = cse->next) {
+ if (cse->x1C > 1 && (cost = cse_cost(cse)) > 4) {
+ if (cse->replaced) {
+ replaces = 0;
+ cse_replace(cse->replaced, cse);
+#line 348
+ CError_ASSERT(replaces >= 1);
+ cse_found = 1;
+ did_replacement = 1;
+ cse_update_usages(cse, cse->x1C);
+ } else {
+ if ((cse->x1C * cost) > best_cost) {
+ best_cse = cse;
+ best_cost = cse->x1C * cost;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (did_replacement)
+ continue;
+ if (!best_cse || extravars >= 256)
+ return;
+
+ obj = lalloc(sizeof(Object));
+ memclrw(obj, sizeof(Object));
+ obj->name = CParser_GetUniqueName();
+ obj->type = cse->expr->rtype;
+ obj->datatype = DLOCAL;
+ vi = CodeGen_GetNewVarInfo();
+ obj->u.var.info = vi;
+
+ objlist = lalloc(sizeof(ObjectList));
+ objlist->object = obj;
+ objlist->next = locals;
+ locals = objlist;
+
+ vi->used = 1;
+ vi->usage = cse->x1C + 1;
+
+ expr1 = lalloc(sizeof(ENode));
+ expr1->type = EOBJREF;
+ expr1->cost = 0;
+ expr1->flags = 0;
+ expr1->data.objref = obj;
+ expr1->rtype = CDecl_NewPointerType(obj->type);
+
+ expr2 = lalloc(sizeof(ENode));
+ expr2->type = EINDIRECT;
+ expr2->cost = 1;
+ expr2->flags = 0;
+ expr2->data.monadic = expr1;
+ expr2->rtype = obj->type;
+
+ expr3 = lalloc(sizeof(ENode));
+ expr3->type = EASS;
+ expr3->cost = -1;
+ expr3->flags = 0;
+ expr3->rtype = obj->type;
+ expr3->data.diadic.left = expr2;
+ expr3->data.diadic.right = lalloc(sizeof(ENode));
+
+ *expr3->data.diadic.right = *cse->expr;
+ cse->expr = expr3->data.diadic.right;
+
+ replaces = 0;
+ cse_replace(expr2, cse);
+ cse->replaced = expr2;
+
+ if (replaces < 2) {
+#line 390
+ CError_FATAL();
+ } else {
+ cse_found = 1;
+ }
+
+ expr4 = lalloc(sizeof(ENode));
+ *expr4 = *cse->mexpr;
+
+ cse->mexpr->type = ECOMMA;
+ cse->mexpr->data.diadic.left = expr3;
+ cse->mexpr->data.diadic.right = expr4;
+
+ cse_update_usages(cse, cse->x1C);
+ extravars++;
+
+ mexprsave = cse->mexpr;
+ if (mexpr == mexprsave)
+ mexpr = expr4;
+
+ for (list = cselist; list; list = list->next) {
+ if (list->cse && !cse_issubcse(list->cse, cse)) {
+ if (list->cse->mexpr == mexprsave)
+ list->cse->mexpr = expr4;
+ if (list->cse->expr == mexprsave)
+ list->cse->expr = expr4;
+ if (list->expr == mexprsave)
+ list->expr = expr4;
+ }
+ }
+ }
+}
+
+static COptCSE *cse_intconst(ENode *expr) {
+ COptCSE *cse = csenodes[EINTCONST];
+
+ for (; cse; cse = cse->next) {
+ if (expr->rtype == cse->expr->rtype)
+ if (CInt64_Equal(cse->expr->data.intval, expr->data.intval))
+ return cse;
+ }
+
+ cse = cse_new(expr);
+ cse->next = csenodes[EINTCONST];
+ csenodes[EINTCONST] = cse;
+ return cse;
+}
+
+static COptCSE *cse_floatconst(ENode *expr) {
+ COptCSE *cse = csenodes[EFLOATCONST];
+ Float val = expr->data.floatval;
+
+ for (; cse; cse = cse->next) {
+ if (CMach_CalcFloatDiadicBool(cse->expr->rtype, cse->expr->data.floatval, TK_LOGICAL_EQ, val))
+ if (expr->rtype == cse->expr->rtype)
+ return cse;
+ }
+
+ cse = cse_new(expr);
+ cse->next = csenodes[EFLOATCONST];
+ csenodes[EFLOATCONST] = cse;
+ return cse;
+}
+
+static COptCSE *cse_vectorconst(ENode *expr) {
+ COptCSE *cse = csenodes[EVECTOR128CONST];
+ MWVector128 val = expr->data.vector128val;
+
+ for (; cse; cse = cse->next) {
+ if (CMach_CalcVectorDiadicBool(cse->expr->rtype, &cse->expr->data.vector128val, TK_LOGICAL_EQ, &val))
+ if (expr->rtype == cse->expr->rtype)
+ return cse;
+ }
+
+ cse = cse_new(expr);
+ cse->next = csenodes[EVECTOR128CONST];
+ csenodes[EVECTOR128CONST] = cse;
+ return cse;
+}
+
+static COptCSE *cse_objref(ENode *expr) {
+ COptCSE *cse = csenodes[EOBJREF];
+ Object *obj = expr->data.objref;
+
+ for (; cse; cse = cse->next) {
+ if (cse->expr->data.objref == obj)
+ return cse;
+ }
+
+ cse = cse_new(expr);
+ cse->next = csenodes[EOBJREF];
+ csenodes[EOBJREF] = cse;
+ return cse;
+}
+
+static COptCSE *cse_add_monadic_node(ENode *outer, COptCSE *innercse) {
+ COptCSE *cse;
+
+ if (!innercse)
+ return NULL;
+
+ for (cse = csenodes[outer->type]; cse; cse = cse->next) {
+ if (cse->left == innercse && cse->expr->rtype == outer->rtype) {
+#line 524
+ CError_ASSERT(cse->expr != outer);
+ cse->x1C++;
+ return cse;
+ }
+ }
+
+ cse = cse_new(outer);
+ cse->next = csenodes[outer->type];
+ csenodes[outer->type] = cse;
+ cse->left = innercse;
+ return cse;
+}
+
+static COptCSE *cse_add_typecon_node(ENode *outer, COptCSE *innercse) {
+ COptCSE *cse;
+
+ if (!innercse)
+ return NULL;
+
+ for (cse = csenodes[outer->type]; cse; cse = cse->next) {
+ if (cse->left == innercse && cse->expr->rtype == outer->rtype) {
+#line 552
+ CError_ASSERT(cse->expr != outer);
+ cse->x1C++;
+ return cse;
+ }
+ }
+
+ cse = cse_new(outer);
+ cse->next = csenodes[outer->type];
+ csenodes[outer->type] = cse;
+ cse->left = innercse;
+ return cse;
+}
+
+static COptCSE *cse_add_diadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) {
+ COptCSE *cse;
+
+ if (!leftcse || !rightcse)
+ return NULL;
+
+ for (cse = csenodes[outer->type]; cse; cse = cse->next) {
+ if (cse->left == leftcse && cse->right == rightcse) {
+#line 581
+ CError_ASSERT(cse->expr != outer);
+ cse->x1C++;
+ return cse;
+ }
+ }
+
+ cse = cse_new(outer);
+ cse->next = csenodes[outer->type];
+ csenodes[outer->type] = cse;
+ cse->left = leftcse;
+ cse->right = rightcse;
+ return cse;
+}
+
+static COptCSE *cse_add_commdiadic_node(ENode *outer, COptCSE *leftcse, COptCSE *rightcse) {
+ COptCSE *cse;
+
+ if (!leftcse || !rightcse)
+ return NULL;
+
+ for (cse = csenodes[outer->type]; cse; cse = cse->next) {
+ if ((cse->left == leftcse && cse->right == rightcse) || (cse->left == rightcse && cse->right == leftcse)) {
+#line 612
+ CError_ASSERT(cse->expr != outer);
+ cse->x1C++;
+ return cse;
+ }
+ }
+
+ cse = cse_new(outer);
+ cse->next = csenodes[outer->type];
+ csenodes[outer->type] = cse;
+ cse->left = leftcse;
+ cse->right = rightcse;
+ return cse;
+}
+
+static void sfind_objref(ENode *expr) {
+ while (1) {
+ switch (expr->type) {
+ case ETYPCON:
+ expr = expr->data.monadic;
+ break;
+ case EOBJREF:
+ objrefnode = expr;
+ objrefnodes++;
+ return;
+ case EADD:
+ case ESUB:
+ sfind_objref(expr->data.diadic.left);
+ expr = expr->data.diadic.right;
+ break;
+ default:
+ return;
+ }
+ }
+}
+
+static ENode *find_objref_node(ENode *expr) {
+ objrefnode = NULL;
+ objrefnodes = 0;
+ sfind_objref(expr);
+ if (objrefnodes == 1)
+ return objrefnode;
+ else
+ return NULL;
+}
+
+static void cse_mem_modify(void) {
+ COptCSE *cse;
+
+ for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) {
+ if (ENODE_IS(cse->expr->data.monadic, EOBJREF)) {
+ Object *obj = cse->expr->data.monadic->data.objref;
+#line 672
+ CError_ASSERT(obj->datatype != DALIAS);
+ if (obj->datatype == DLOCAL && !obj->u.var.info->noregister)
+ continue;
+ }
+
+ cse_inval(cse);
+ }
+}
+
+static void cse_modify_expression(ENode *expr) {
+ if (!expr) {
+ short op;
+
+ cse_remove();
+ for (op = 0; op < MAXEXPR; op++)
+ csenodes[op] = NULL;
+
+ cselist = NULL;
+ freeoheap();
+ } else {
+ ENode *objnode;
+ Object *obj;
+ COptCSE *cse;
+
+ cse_invals = 1;
+ if (ENODE_IS(expr, EINDIRECT) && (objnode = find_objref_node(expr->data.monadic))) {
+ do {
+ obj = objnode->data.objref;
+ cse_remove();
+ for (cse = csenodes[EINDIRECT]; cse; cse = cse->next) {
+ if ((objnode = find_objref_node(cse->expr->data.monadic)) && obj == objnode->data.objref)
+ cse_inval(cse);
+ }
+
+ objnode = find_objref_node(expr->data.monadic);
+ if (!objnode) {
+ cse_mem_modify();
+ break;
+ }
+ } while (obj != objnode->data.objref);
+ } else {
+ cse_remove();
+ cse_mem_modify();
+ }
+ }
+}
+
+static void cse_pascalcall(ENode *expr) {
+ ENodeList *list;
+
+ for (list = expr->data.funccall.args; list; list = list->next)
+ cse_expression(list->node);
+
+ if (ENODE_IS(expr, EFUNCCALLP))
+ cse_expression(expr->data.funccall.funcref);
+
+ cse_remove();
+ cse_mem_modify();
+}
+
+static Boolean cse_pusharg(ENodeList *exprs, FuncArg *args) {
+ Boolean result;
+
+ if (!exprs)
+ return 1;
+
+ if (args && args != &elipsis && args != &oldstyle)
+ args = args->next;
+ if (exprs->next)
+ result = cse_pusharg(exprs->next, args);
+
+ cse_expression(exprs->node);
+ return result;
+}
+
+static void cse_ccall(ENode *expr) {
+ if (cse_pusharg(expr->data.funccall.args, expr->data.funccall.functype->args)) {
+ if (ENODE_IS(expr, EFUNCCALL))
+ cse_expression(expr->data.funccall.funcref);
+
+ cse_remove();
+ cse_mem_modify();
+ } else {
+ cse_modify_expression(NULL);
+ }
+}
+
+static COptCSE *cse_expression(ENode *expr) {
+ ENode *save;
+ COptCSE *tmp;
+ ENodeType nt = expr->type;
+
+ switch (nt) {
+ case EFUNCCALL:
+ cse_ccall(expr);
+ return NULL;
+ case EFUNCCALLP:
+ cse_pascalcall(expr);
+ return NULL;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ save = mexpr;
+ mexpr = expr;
+#line 816
+ CError_ASSERT(ENODE_IS(expr->data.monadic, EINDIRECT));
+
+ cse_expression(expr->data.monadic->data.monadic);
+ cse_modify_expression(expr->data.monadic);
+ mexpr = save;
+ return NULL;
+
+ case EINDIRECT:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ return cse_append(cse_add_monadic_node(expr, cse_expression(expr->data.monadic)), expr);
+
+ case ETYPCON:
+ return cse_append(cse_add_typecon_node(expr, cse_expression(expr->data.monadic)), expr);
+
+ case EMUL:
+ case EMULV:
+ case EADDV:
+ case EADD:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EXOR:
+ case EOR:
+ tmp = cse_expression(expr->data.diadic.left);
+ if (expr->type == nt)
+ return cse_append(cse_add_commdiadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr);
+ else
+ return NULL;
+
+ case EDIV:
+ case EMODULO:
+ case ESUBV:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EPMODULO:
+ case EROTL:
+ case EROTR:
+ case EBTST:
+ tmp = cse_expression(expr->data.diadic.left);
+ if (expr->type == nt)
+ return cse_append(cse_add_diadic_node(expr, tmp, cse_expression(expr->data.diadic.right)), expr);
+ else
+ return NULL;
+
+ case EASS:
+ case EMULASS:
+ case EDIVASS:
+ case EMODASS:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EANDASS:
+ case EXORASS:
+ case EORASS:
+#line 887
+ CError_ASSERT(ENODE_IS(expr->data.diadic.left, EINDIRECT));
+ save = mexpr;
+ mexpr = expr;
+ cse_expression(expr->data.diadic.right);
+ if (expr->type == nt) {
+ cse_expression(expr->data.diadic.left->data.monadic);
+ cse_modify_expression(expr->data.diadic.left);
+ mexpr = save;
+ return NULL;
+ } else {
+ cse_modify_expression(NULL);
+ return NULL;
+ }
+
+ case ECOMMA:
+ cse_expression(expr->data.diadic.left);
+ save = mexpr;
+ mexpr = expr->data.diadic.right;
+ tmp = cse_expression(expr->data.diadic.right);
+ mexpr = save;
+ return tmp;
+
+ case EINTCONST:
+ return cse_intconst(expr);
+ case EFLOATCONST:
+ return cse_floatconst(expr);
+ case EVECTOR128CONST:
+ return cse_vectorconst(expr);
+ case EOBJREF:
+ return cse_objref(expr);
+
+ case EBITFIELD:
+ cse_modify_expression(NULL);
+ return NULL;
+
+ case ECOND:
+ cse_expression(expr->data.cond.cond);
+ cse_modify_expression(NULL);
+ return NULL;
+
+ case ENULLCHECK:
+ cse_expression(expr->data.nullcheck.nullcheckexpr);
+ cse_modify_expression(NULL);
+ return NULL;
+
+ case ELAND:
+ case ELOR:
+ cse_expression(expr->data.diadic.left);
+ cse_modify_expression(NULL);
+ return NULL;
+
+ case ESTRINGCONST:
+ case ELABEL:
+ return NULL;
+
+ case EPRECOMP:
+#line 948
+ CError_FATAL();
+
+ default:
+#line 951
+ CError_FATAL();
+ return NULL;
+ }
+}
+
+static void cse_block(COptBlock *block) {
+ Statement *stmt;
+ COptBlock *check;
+ COptBlockList *scan;
+ COptBlock *best;
+ short i;
+ SInt32 counter;
+ UInt32 starttime;
+
+ starttime = COS_GetTicks();
+ counter = 0;
+
+ while (1) {
+ cse_invals = 0;
+ currentblock = block;
+ block->x1E = 1;
+
+ for (stmt = block->stmt, i = block->x1C; i > 0; stmt = stmt->next, i--) {
+ switch (stmt->type) {
+ case ST_EXPRESSION:
+ case ST_SWITCH:
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ mexpr = stmt->expr;
+ cse_expression(mexpr);
+ break;
+ case ST_RETURN:
+ mexpr = stmt->expr;
+ if (mexpr)
+ cse_expression(mexpr);
+ break;
+ }
+ }
+
+ i = 0;
+ for (scan = block->blocks2; scan; scan = scan->next) {
+ check = scan->block;
+ if (!check->x1E && check->blocks && !check->blocks->next && check->blocks->block == block) {
+ best = check;
+ i++;
+ }
+ }
+
+ if (i != 1)
+ break;
+
+ block = best;
+ if (COS_GetTicks() > (starttime + 60)) {
+ if (counter++ & 1) {
+ if (CWDisplayLines(cparamblkptr->context, lines))
+ CError_UserBreak();
+ } else {
+ if (CWDisplayLines(cparamblkptr->context, lines + 1))
+ CError_UserBreak();
+ }
+ starttime = COS_GetTicks();
+ }
+
+ if (cse_invals)
+ cse_cleanup();
+ }
+
+ cse_remove();
+}
+
+static void CSE(void) {
+ COptBlock *block;
+
+ for (block = basicblocks->next; block; block = block->next)
+ block->x1E = 0;
+
+ for (block = basicblocks->next; block; block = block->next) {
+ if (!block->x1E) {
+ short op;
+
+ for (op = 0; op < MAXEXPR; op++)
+ csenodes[op] = NULL;
+
+ cselist = NULL;
+ cse_found = 0;
+ cse_block(block);
+ freeoheap();
+ }
+ }
+}
+
+static short TestSetBit(short *set, short bit) {
+ return set[bit >> 4] & bitmasks[bit & 15];
+}
+
+static void SetSetBit(short *set, short bit) {
+ set[bit >> 4] |= bitmasks[bit & 15];
+}
+
+UInt32 RegAllocMask(short var) {
+ COptBlock *block;
+ UInt32 mask = 0;
+
+ for (block = basicblocks; block; block = block->next) {
+ if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var))
+ mask |= block->allocmask;
+ }
+
+ return mask;
+}
+
+void MarkRegAllocMask(short var, short bit, Boolean flag) {
+ COptBlock *block;
+ UInt32 mask = 1 << bit;
+
+ if (flag) {
+ for (block = basicblocks; block; block = block->next) {
+ if (TestSetBit(block->set1, var) || TestSetBit(block->set2, var))
+ block->allocmask |= mask;
+ }
+ } else {
+ for (block = basicblocks; block; block = block->next) {
+ block->allocmask |= mask;
+ }
+ }
+}
+
+static COptBlock *newblock(void) {
+ COptBlock *block;
+ short i;
+ short max;
+
+ block = lalloc(sizeof(COptBlock) + (setbytes * 2));
+ block->x1E = 0;
+ block->next = NULL;
+ block->blocks = NULL;
+ block->blocks2 = NULL;
+ block->allocmask = 0;
+ block->set1 = (short *) (((long) block) + sizeof(COptBlock));
+ block->set2 = (short *) (((long) block) + setbytes + sizeof(COptBlock));
+
+ for (i = 0, max = setbytes / 2; i < max; i++) {
+ block->set1[i] = 0;
+ block->set2[i] = 0;
+ }
+}
+
+static void MarkFollow(COptBlock *block) {
+ COptBlockList *list;
+
+restart:
+ block->x1E = 1;
+ if ((list = block->blocks2)) {
+ while (1) {
+ if (!list->block->x1E) {
+ if (!list->next) {
+ block = list->block;
+ goto restart;
+ }
+ MarkFollow(list->block);
+ list = list->next;
+ } else {
+ list = list->next;
+ if (!list)
+ break;
+ }
+ }
+ }
+}
+
+static Boolean CheckInit(short var) {
+ Boolean result;
+ COptBlock *block;
+
+ result = 1;
+ for (block = basicblocks; block; block = block->next) {
+ if (!block->x1E && TestSetBit(block->set2, var))
+ MarkFollow(block);
+ }
+
+ for (block = basicblocks; block; block = block->next) {
+ if (!block->x1E) {
+ if (TestSetBit(block->set1, var))
+ result = 0;
+ } else {
+ block->x1E = 0;
+ }
+ }
+
+ return result;
+}
+
+static void CheckVarInit(void) {
+ COptBlock *block;
+ VarInfo *vi;
+ ObjectList *list;
+
+ for (block = basicblocks; block; block = block->next)
+ block->x1E = 0;
+
+ for (list = locals; list; list = list->next) {
+ if (list->object->datatype == DLOCAL && !IsTempName(list->object->name) && !is_volatile_object(list->object)) {
+ vi = list->object->u.var.info;
+ if (vi->used && !CheckInit(vi->varnumber)) {
+ if (!IS_TYPE_CLASS(list->object->type) || !CClass_IsEmpty(TYPE_CLASS(list->object->type))) {
+ CError_SetErrorToken(&vi->deftoken);
+ CError_Warning(CErrorStr185, list->object->name->name);
+ }
+ }
+ }
+ }
+}
+
+static void AddVar(Object *obj, Boolean whichSet) {
+ VarInfo *vi;
+
+ if (obj->datatype == DLOCAL) {
+ vi = obj->u.var.info;
+ if (!whichSet) {
+ SetSetBit(currentblock->set1, vi->varnumber);
+ } else {
+ if (!TestSetBit(currentblock->set1, vi->varnumber))
+ SetSetBit(currentblock->set2, vi->varnumber);
+ }
+ }
+}
+
+static void CheckExpr(ENode *expr) {
+ ENodeList *list;
+
+ while (1) {
+ switch (expr->type) {
+ case EINDIRECT:
+ if (ENODE_IS(expr->data.monadic, EOBJREF)) {
+ AddVar(expr->data.monadic->data.objref, 0);
+ return;
+ }
+ expr = expr->data.monadic;
+ break;
+ case EOBJREF:
+ AddVar(expr->data.objref, 1);
+ return;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ CheckExpr(expr->data.funccall.funcref);
+ for (list = expr->data.funccall.args; list; list = list->next)
+ CheckExpr(list->node);
+ return;
+ case ECOND:
+ CheckExpr(expr->data.cond.cond);
+ CheckExpr(expr->data.cond.expr1);
+ CheckExpr(expr->data.cond.expr2);
+ return;
+ case EASS:
+ if (ENODE_IS_INDIRECT_TO(expr->data.diadic.left, EOBJREF)) {
+ CheckExpr(expr->data.diadic.right);
+ AddVar(expr->data.diadic.left->data.monadic->data.objref, 1);
+ return;
+ }
+ 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 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:
+ CheckExpr(expr->data.diadic.left);
+ expr = expr->data.diadic.right;
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ expr = expr->data.monadic;
+ break;
+ case ENULLCHECK:
+ CheckExpr(expr->data.nullcheck.nullcheckexpr);
+ expr = expr->data.nullcheck.condexpr;
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case ESTRINGCONST:
+ case EPRECOMP:
+ case ELABEL:
+ case EVECTOR128CONST:
+ return;
+ default:
+#line 1332
+ CError_FATAL();
+ }
+ }
+}
+
+static short CheckPath(COptBlock *block, short var) {
+ COptBlockList *list;
+
+ if (block->x1E)
+ return TestSetBit(block->set1, var);
+
+ block->x1E = 1;
+ if (TestSetBit(block->set1, var))
+ return -1;
+ if (TestSetBit(block->set2, var))
+ return 0;
+
+ for (list = block->blocks2; list; list = list->next) {
+ if (CheckPath(list->block, var)) {
+ SetSetBit(block->set1, var);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void MarkPre(COptBlock *block, short var) {
+ COptBlockList *list;
+
+restart:
+ block->x1E = 1;
+ for (list = block->blocks; list; list = list->next) {
+ if (!list->block->x1E) {
+ if (!TestSetBit(list->block->set2, var)) {
+ SetSetBit(list->block->set1, var);
+ if (!list->next) {
+ block = list->block;
+ goto restart;
+ }
+ MarkPre(list->block, var);
+ } else {
+ list->block->x1E = 1;
+ }
+ }
+ }
+}
+
+static void CheckVarUsage(void) {
+ short local;
+ COptBlock *block;
+ short counter;
+
+ for (currentblock = basicblocks; currentblock; currentblock = currentblock->next) {
+ Statement *stmt = currentblock->stmt;
+ if (currentblock->x1C > 0 && stmt->type == ST_LABEL && (stmt->flags & StmtFlag_1)) {
+ short i;
+ for (i = 0; i < localcount; i++)
+ SetSetBit(currentblock->set2, i);
+ }
+
+ for (counter = currentblock->x1C; counter > 0; counter--) {
+ if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR && stmt->expr)
+ CheckExpr(stmt->expr);
+ stmt = stmt->next;
+ }
+ }
+
+ for (local = 0; local < localcount; local++) {
+ for (block = basicblocks; block; block = block->next) {
+ if (!block->x1E && TestSetBit(block->set1, local))
+ MarkPre(block, local);
+ }
+ for (block = basicblocks; block; block = block->next) {
+ block->x1E = 0;
+ }
+ }
+}
+
+static void SplitCommaExpressions(void) {
+ COptBlock *block;
+ Statement *stmt;
+ ENode *expr;
+ Statement *stmtcopy;
+ short counter;
+ Boolean flag;
+
+ block = basicblocks->next;
+ while (block) {
+ stmt = block->stmt;
+ counter = block->x1C;
+ flag = 1;
+ while (counter > 0) {
+ if (stmt->type >= ST_EXPRESSION && stmt->type <= ST_GOTOEXPR) {
+ if ((expr = stmt->expr) && ENODE_IS(expr, ECOMMA)) {
+ stmtcopy = lalloc(sizeof(Statement));
+ *stmtcopy = *stmt;
+ stmt->next = stmtcopy;
+ stmt->type = ST_EXPRESSION;
+ stmt->expr = expr->data.diadic.left;
+ stmtcopy->expr = expr->data.diadic.right;
+ block->x1C++;
+ flag = 0;
+ break;
+ }
+ }
+
+ stmt = stmt->next;
+ counter--;
+ }
+
+ if (flag)
+ block = block->next;
+ }
+}
+
+static void BasicBlockAnalyze(Statement *stmt) {
+ COptBlock *block;
+ ObjectList *objlist;
+ COptBlockList *scan;
+ COptBlockList *list;
+ CLabel *label;
+ COptBlock *iblock;
+ COptBlock *oblock;
+ SwitchCase *swcase;
+
+ setbytes = 2 * ((localcount - 1) / 16) + 2;
+ if (copts.global_optimizer) {
+ setbytes += 32;
+ extravars = 0;
+ }
+
+ block = newblock();
+ basicblocks = block;
+ block->stmt = NULL;
+ block->x1C = 0;
+
+ if (stmt) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = NULL;
+ block->blocks2 = list;
+ list->block = (COptBlock *) stmt;
+ }
+
+ for (objlist = arguments; objlist; objlist = objlist->next) {
+ SetSetBit(block->set2, objlist->object->u.var.info->varnumber);
+ }
+
+ while (stmt) {
+ int counter;
+
+ block->next = newblock();
+ block = block->next;
+ block->stmt = stmt;
+ counter = 1;
+
+ innerLoop:
+ switch (stmt->type) {
+ case ST_ASM:
+ label = InlineAsm_GetReferencedLabel(stmt);
+ if (!label)
+ goto jumpahead;
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) label->stmt;
+ if (stmt->next) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) stmt->next;
+ }
+ stmt = stmt->next;
+ block->x1C = counter;
+ continue;
+ case ST_NOP:
+ case ST_GOTO:
+ case ST_ENTRY:
+ if (stmt->next && stmt->next->type != ST_LABEL) {
+ stmt = stmt->next;
+ counter++;
+ goto innerLoop;
+ }
+ break;
+ case ST_EXPRESSION:
+ case ST_BEGINCATCH:
+ case ST_ENDCATCH:
+ case ST_ENDCATCHDTOR:
+ jumpahead:
+ if (stmt->next && stmt->next->type == ST_GOTO) {
+ stmt = stmt->next;
+ counter++;
+ goto innerLoop;
+ }
+ break;
+ }
+
+ switch (stmt->type) {
+ case ST_SWITCH:
+ label = ((SwitchInfo *) stmt->label)->defaultlabel;
+ if (label != cleanreturnlabel) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) label->stmt;
+ }
+ for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next) {
+ label = swcase->label;
+ if (label != cleanreturnlabel) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) label->stmt;
+ }
+ }
+ break;
+ case ST_RETURN:
+ case ST_EXIT:
+ case ST_GOTOEXPR:
+ break;
+ case ST_GOTO:
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ case ST_OVF:
+ label = stmt->label;
+ if (label != cleanreturnlabel) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) label->stmt;
+ }
+ if (stmt->type == ST_GOTO)
+ break;
+ default:
+ if (stmt->next) {
+ list = lalloc(sizeof(COptBlockList));
+ list->next = block->blocks2;
+ block->blocks2 = list;
+ list->block = (COptBlock *) stmt->next;
+ }
+ break;
+ }
+
+ stmt = stmt->next;
+ block->x1C = counter;
+ }
+
+ for (oblock = basicblocks; oblock; oblock = oblock->next) {
+ for (scan = oblock->blocks2; scan; scan = scan->next) {
+ stmt = (Statement *) scan->block;
+ for (iblock = basicblocks->next; iblock; iblock = iblock->next) {
+ if (iblock->stmt == stmt) {
+ scan->block = iblock;
+ list = lalloc(sizeof(COptBlockList));
+ list->next = iblock->blocks;
+ iblock->blocks = list;
+ list->block = oblock;
+ break;
+ }
+ }
+
+#line 1602
+ CError_ASSERT(iblock);
+ }
+ }
+
+ SplitCommaExpressions();
+ CheckVarUsage();
+}
+
+static CLabel *finallabel(CLabel *label, Statement *stmt) {
+ Statement *scan;
+
+ for (scan = label->stmt; scan; scan = scan->next) {
+ if (scan->type > ST_LABEL) {
+ if (scan == stmt)
+ return label;
+ if (scan->type == ST_GOTO) {
+ if (scan->label != label)
+ stmtchanged = 1;
+ return scan->label;
+ }
+ return label;
+ }
+ }
+}
+
+static void optimizegoto(Statement *stmt) {
+ Statement *scan;
+
+ for (scan = stmt->next; scan; scan = scan->next) {
+ if (stmt->label->stmt == scan) {
+ stmt->type = ST_NOP;
+ stmtchanged = 1;
+ return;
+ }
+ if (scan->type > ST_LABEL)
+ break;
+ }
+
+ stmt->label = finallabel(stmt->label, stmt);
+}
+
+static void removeif(Statement *stmt, Boolean flag) {
+ if (((stmt->type == ST_IFGOTO) && flag) || ((stmt->type == ST_IFNGOTO) && !flag)) {
+ Statement *copy = lalloc(sizeof(Statement));
+ *copy = *stmt;
+ copy->type = ST_GOTO;
+ stmt->next = copy;
+ }
+ stmt->type = ST_EXPRESSION;
+ stmtchanged = 1;
+}
+
+static void optimizeif(Statement *stmt) {
+}
+
+static void optimizeswitch(Statement *stmt) {
+ SwitchInfo *info;
+ SwitchCase *swcase;
+
+ info = (SwitchInfo *) stmt->label;
+#line 1746
+ CError_ASSERT(info && info->cases && info->defaultlabel);
+
+ info->defaultlabel = finallabel(info->defaultlabel, stmt);
+ for (swcase = info->cases; swcase; swcase = swcase->next)
+ swcase->label = finallabel(swcase->label, stmt);
+
+ if (ENODE_IS(stmt->expr, EINTCONST)) {
+ for (swcase = info->cases; swcase; swcase = swcase->next) {
+ if (CInt64_GreaterEqual(swcase->min, stmt->expr->data.intval) && CInt64_LessEqual(swcase->max, stmt->expr->data.intval))
+ break;
+ }
+
+ stmt->type = ST_GOTO;
+ stmt->label = swcase ? swcase->label : info->defaultlabel;
+ }
+}
+
+static void removeunusedlabels(Statement *stmt) {
+ Statement *scan;
+ CLabel *label;
+ SwitchCase *swcase;
+ ExceptionAction *action;
+
+ for (scan = stmt; scan; scan = scan->next)
+ scan->marked = 0;
+
+ for (scan = stmt; scan; scan = scan->next) {
+ switch (scan->type) {
+ case ST_GOTO:
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ case ST_OVF:
+ if (scan->label->stmt)
+ scan->label->stmt->marked = 1;
+ break;
+ case ST_SWITCH:
+ ((SwitchInfo *) scan->label)->defaultlabel->stmt->marked = 1;
+ for (swcase = ((SwitchInfo *) scan->label)->cases; swcase; swcase = swcase->next)
+ swcase->label->stmt->marked = 1;
+ break;
+ case ST_ASM:
+ if ((label = InlineAsm_GetReferencedLabel(scan)))
+ label->stmt->marked = 1;
+ if ((label = InlineAsm_GetReferencedLabel2(scan)))
+ label->stmt->marked = 1;
+ break;
+ case ST_BEGINLOOP:
+ ((LoopInfo *) scan->expr)->stmt->marked = 1;
+ break;
+ case ST_ENDLOOP:
+ if (scan->next->type == ST_GOTO && scan->next->next->type == ST_LABEL)
+ scan->next->next->marked = 1;
+ break;
+ default:
+ for (action = scan->dobjstack; action; action = action->prev) {
+ if (action->type == EAT_CATCHBLOCK) {
+ action->data.catch_block.catch_label->stmt->marked = 1;
+ action->data.catch_block.catch_label->stmt->flags |= StmtFlag_1;
+ } else if (action->type == EAT_SPECIFICATION) {
+ action->data.specification.unexp_label->stmt->marked = 1;
+ action->data.specification.unexp_label->stmt->flags |= StmtFlag_1;
+ }
+ }
+ }
+ }
+
+ for (scan = stmt; scan; scan = scan->next) {
+ if (scan->type == ST_LABEL && !scan->marked && !(scan->flags & StmtFlag_1)) {
+ scan->type = ST_NOP;
+ stmtchanged = 1;
+ }
+ }
+}
+
+static void optimizebranches(Statement *stmt) {
+ removeunusedlabels(stmt);
+ while (stmt) {
+ switch (stmt->type) {
+ case ST_GOTO:
+ optimizegoto(stmt);
+ break;
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ optimizeif(stmt);
+ break;
+ case ST_SWITCH:
+ optimizeswitch(stmt);
+ break;
+ }
+ stmt = stmt->next;
+ }
+}
+
+void SetVarUsage(Object *obj, Boolean noregister) {
+ VarInfo *vi;
+#line 1875
+ CError_ASSERT(obj->datatype != DALIAS);
+
+ if (obj->datatype == DLOCAL || obj->datatype == DNONLAZYPTR) {
+ vi = obj->u.var.info;
+ vi->used = 1;
+ if (!copts.global_optimizer) {
+ if (copts.optimize_for_size)
+ vi->usage++;
+ else
+ vi->usage += curstmtvalue;
+ }
+
+ if (noregister)
+ vi->noregister = 1;
+ }
+}
+
+static void checkexpression(ENode *expr) {
+ ENodeList *list;
+
+ while (1) {
+ switch (expr->type) {
+ case EOBJREF:
+ SetVarUsage(expr->data.objref, 1);
+ return;
+ case EINDIRECT:
+ if (ENODE_IS(expr->data.monadic, EOBJREF)) {
+ SetVarUsage(expr->data.monadic->data.objref, 0);
+ return;
+ }
+ expr = expr->data.monadic;
+ break;
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ copt_isleaffunction = 0;
+ checkexpression(expr->data.funccall.funcref);
+ for (list = expr->data.funccall.args; list; list = list->next)
+ checkexpression(list->node);
+ return;
+ case ECOND:
+ case ECONDASS:
+ checkexpression(expr->data.cond.cond);
+ checkexpression(expr->data.cond.expr1);
+ checkexpression(expr->data.cond.expr2);
+ return;
+ 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:
+ checkexpression(expr->data.diadic.left);
+ expr = expr->data.diadic.right;
+ break;
+ case EPOSTINC:
+ case EPOSTDEC:
+ case EPREINC:
+ case EPREDEC:
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ case EFORCELOAD:
+ case ETYPCON:
+ case EBITFIELD:
+ expr = expr->data.monadic;
+ break;
+ case ENULLCHECK:
+ checkexpression(expr->data.nullcheck.nullcheckexpr);
+ expr = expr->data.nullcheck.condexpr;
+ break;
+ case EINTCONST:
+ case EFLOATCONST:
+ case EPRECOMP:
+ case ELABEL:
+ case EVECTOR128CONST:
+ return;
+ case ESTRINGCONST:
+ return;
+ default:
+#line 1998
+ CError_FATAL();
+ }
+ }
+}
+
+static void checklocalusage(Statement *stmt) {
+ Statement *scan;
+
+ for (scan = stmt; scan; scan = scan->next) {
+ if (scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR && scan->expr) {
+ curstmtvalue = scan->value;
+ checkexpression(scan->expr);
+ } else if (scan->type == ST_ASM) {
+ curstmtvalue = scan->value;
+ InlineAsm_CheckLocalUsage(scan);
+ }
+ }
+}
+
+static void colorcode(Statement *stmt) {
+ CLabel *label;
+ SwitchCase *swcase;
+
+ while (stmt && !stmt->marked) {
+ stmt->marked = 1;
+ switch (stmt->type) {
+ case ST_GOTOEXPR:
+ return;
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ case ST_OVF:
+ colorcode(stmt->label->stmt);
+ break;
+ case ST_GOTO:
+ case ST_EXIT:
+ stmt = stmt->label->stmt;
+ continue;
+ case ST_RETURN:
+ return;
+ case ST_SWITCH:
+ for (swcase = ((SwitchInfo *) stmt->label)->cases; swcase; swcase = swcase->next)
+ colorcode(swcase->label->stmt);
+ stmt = ((SwitchInfo *) stmt->label)->defaultlabel->stmt;
+ continue;
+ case ST_ASM:
+ if ((label = InlineAsm_GetReferencedLabel(stmt)))
+ colorcode(label->stmt);
+ if ((label = InlineAsm_GetReferencedLabel2(stmt)))
+ colorcode(label->stmt);
+ break;
+ case ST_ENDLOOP:
+ if (stmt->next && stmt->next->type == ST_GOTO) {
+ stmt = stmt->next;
+ stmt->marked = 1;
+ }
+ break;
+ case ST_NOP:
+ case ST_LABEL:
+ case ST_EXPRESSION:
+ case ST_ENTRY:
+ case ST_BEGINCATCH:
+ case ST_ENDCATCH:
+ case ST_ENDCATCHDTOR:
+ case ST_BEGINLOOP:
+ break;
+ default:
+#line 2096
+ CError_FATAL();
+ }
+ stmt = stmt->next;
+ }
+}
+
+static void removeunusedcode(Statement *stmt) {
+ Statement *scan;
+
+ for (scan = stmt; scan; scan = scan->next)
+ scan->marked = 0;
+
+ colorcode(stmt);
+ for (scan = stmt; scan; scan = scan->next) {
+ if (!scan->marked && (scan->flags & StmtFlag_1))
+ colorcode(scan);
+ }
+
+ for (scan = stmt; scan; scan = scan->next) {
+ if (!scan->marked && scan->type != ST_NOP) {
+ scan->type = ST_NOP;
+ stmtchanged = 1;
+ }
+ }
+}
+
+static void COpt_ReturnCheck(Object *obj, Statement *stmt) {
+ if ((copts.pedantic || copts.cplusplus) && obj && TYPE_FUNC(obj->type)->functype != &stvoid) {
+ while (stmt) {
+ if (!stmt->next && stmt->type != ST_GOTO && stmt->type != ST_RETURN) {
+ CError_Warning(CErrorStr184);
+ break;
+ }
+
+ if (stmt->type == ST_RETURN && !stmt->expr && !(stmt->flags & StmtFlag_8)) {
+ CError_Warning(CErrorStr184);
+ break;
+ }
+
+ stmt = stmt->next;
+ }
+ }
+}
+
+static void COpt_Optimize(Object *obj, Statement *stmt) {
+ Statement **ptr;
+
+ do {
+ stmtchanged = 0;
+ optimizebranches(stmt->next);
+ removeunusedcode(stmt->next);
+ } while (stmtchanged);
+
+ ptr = &stmt->next;
+ while (*ptr) {
+ if ((*ptr)->type == ST_NOP)
+ *ptr = (*ptr)->next;
+ else
+ ptr = &(*ptr)->next;
+ }
+}
+
+static void COpt_ELABELCallBack(ENode *expr) {
+#line 2195
+ CError_ASSERT(expr->data.label->stmt && expr->data.label->stmt->type == ST_LABEL);
+ expr->data.label->stmt->flags |= StmtFlag_1;
+}
+
+void COpt_SimpleOptimizer(Object *obj, Statement *stmt) {
+ Statement *scan;
+
+ for (scan = stmt; scan; scan = scan->next) {
+ if ((scan->type >= ST_EXPRESSION && scan->type <= ST_GOTOEXPR) && scan->expr)
+ CExpr_SearchExprTree(scan->expr, COpt_ELABELCallBack, 1, ELABEL);
+ }
+
+ static_for_inlines = 1;
+ cleanreturnlabel = NULL;
+ COpt_Optimize(obj, stmt);
+ COpt_ReturnCheck(obj, stmt);
+}
+
+Statement *COpt_Optimizer(Object *obj, Statement *stmt) {
+ copt_isleaffunction = 1;
+ if (copts.global_optimizer)
+ stmt = IRO_Optimizer(obj, stmt);
+
+ static_for_inlines = 0;
+ COpt_Optimize(obj, stmt);
+
+ if (obj && !(obj->qual & Q_INLINE))
+ COpt_ReturnCheck(obj, stmt);
+
+ checklocalusage(stmt->next);
+ return stmt;
+}
diff --git a/compiler_and_linker/unsorted/CPreprocess.c b/compiler_and_linker/unsorted/CPreprocess.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CPreprocess.c
diff --git a/compiler_and_linker/unsorted/CRTTI.c b/compiler_and_linker/unsorted/CRTTI.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CRTTI.c
diff --git a/compiler_and_linker/unsorted/CSOM.c b/compiler_and_linker/unsorted/CSOM.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CSOM.c
diff --git a/compiler_and_linker/unsorted/CTemplateClass.c b/compiler_and_linker/unsorted/CTemplateClass.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CTemplateClass.c
diff --git a/compiler_and_linker/unsorted/CTemplateFunc.c b/compiler_and_linker/unsorted/CTemplateFunc.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CTemplateFunc.c
diff --git a/compiler_and_linker/unsorted/CTemplateNew.c b/compiler_and_linker/unsorted/CTemplateNew.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CTemplateNew.c
diff --git a/compiler_and_linker/unsorted/CTemplateTools.c b/compiler_and_linker/unsorted/CTemplateTools.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CTemplateTools.c
diff --git a/compiler_and_linker/unsorted/CodeGen.c b/compiler_and_linker/unsorted/CodeGen.c
index 0867270..d87d80f 100644
--- a/compiler_and_linker/unsorted/CodeGen.c
+++ b/compiler_and_linker/unsorted/CodeGen.c
@@ -1,13 +1,63 @@
-#include "compiler.h"
+#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/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/InstrSelection.h"
+#include "compiler/Operands.h"
#include "compiler/PCode.h"
#include "compiler/PCodeInfo.h"
#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/StackFrame.h"
+#include "compiler/TOC.h"
+#include "compiler/CompilerTools.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
+#include "compiler/scopes.h"
#include "compiler/tokens.h"
#include "compiler/types.h"
+// TODO: MOVE ME
+extern void Intrinsics_SetupRuntimeObjects(void);
+extern void Intrinsics_ReInitRuntimeObjects(Boolean);
+extern Boolean Intrinsics_IsPublicRuntimeObject(Object *);
+extern ENode *Intrinsics_HandleIntrinsicCall(Object *func, ENodeList *arg_exprs);
+extern void PPCError_Error(int, ...);
+extern void PPCError_Warning(int, ...);
+extern void PPCError_Message(char *, ...);
+extern void globallyoptimizepcode(Object *);
+extern void pclistblocks(char *, char *);
+extern void pclistblocks_start_scheduler(char *, char *);
+extern void pclistblocks_end_scheduler();
+extern void scheduleinstructions(Boolean);
+extern void peepholemergeblocks(Object *, Boolean);
+extern void peepholeoptimizeforward(Object *);
+extern void peepholeoptimizepcode(Object *);
+extern void colorinstructions(Object *);
+extern void removecommonsubexpressions(Object *, Boolean);
+extern int removedcommonsubexpressions;
+extern SInt32 assemblefunction(Object *, void *);
+extern void dumpswitchtables(Object *);
+extern void ObjGen_DeclareInitFunction(Object *);
+extern void *switchtables;
+extern void initializeexceptiontables();
+extern void dumpexceptiontables(Object *, SInt32);
+extern void switchstatement(ENode *, CLabel *);
+extern void DumpIR(Statement **, Object *);
+extern void InlineAsm_TranslateIRtoPCode(Statement *stmt);
+typedef struct WeirdInlineAsmThing {
+ UInt8 x0, x1, x2;
+} WeirdInlineAsmThing;
+extern Statement **COpt_Optimizer(Object *, Statement **);
+
static Macro powcM;
static Macro __powcM;
static Macro ppc_cpu;
@@ -29,8 +79,8 @@ static Macro dynM;
static Macro ppcM;
Object *gFunction;
static ObjectList *temps;
-PCodeLabel *returnlabel;
-PCodeLabel *cleanreturnlabel;
+CLabel *returnlabel;
+CLabel *cleanreturnlabel;
Boolean needs_cleanup;
Statement *current_statement;
int has_catch_blocks;
@@ -60,7 +110,7 @@ Object *rt_cvt_sll_dbl;
Object *rt_cvt_ull_flt;
Object *rt_cvt_sll_flt;
Object *rt_cvt_dbl_usll;
-static void *saveheaperror;
+static heaperror_t saveheaperror;
enum {
GPRLimit = 10,
@@ -68,6 +118,9 @@ enum {
VRLimit = 13
};
+// forward decls
+static void CodeGen_heaperror(void);
+
VarInfo *CodeGen_GetNewVarInfo(void) {
VarInfo *vi;
@@ -601,10 +654,11 @@ static void load_TOC_pointers(void) {
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);
+ pc = makepcode(PC_BC, 20, 7, 3, pic_base_pcodelabel);
pcsetlinkbit(pc);
pcsetsideeffects(pc);
appendpcode(pclastblock, pc);
@@ -614,24 +668,52 @@ static void load_TOC_pointers(void) {
emitpcode(PC_MFLR, pic_base_reg);
}
- // TODO: depends on Operands
+ 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:
+#line 1206
+ CError_FATAL();
+ }
+ }
}
}
-static Boolean has_vararglist(Object *funcobj) {
+static int has_vararglist(Object *funcobj) {
FuncArg *arg;
arg = TYPE_FUNC(funcobj->type)->args;
while (arg && arg != &elipsis)
arg = arg->next;
- return arg == &elipsis;
+ return (arg == &elipsis);
}
-void assign_labels() {
- // TODO
+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) {
@@ -642,7 +724,7 @@ static Boolean islaststatement(Statement *stmt) {
return 1;
}
-static void newstatement(SInt32 sourceoffset, UInt16 value, int flag) {
+static void newstatement(SInt32 sourceoffset, SInt32 value, int flag) {
PCodeBlock *block = pclastblock;
pcloopweight = value;
@@ -657,41 +739,1685 @@ static void newstatement(SInt32 sourceoffset, UInt16 value, int flag) {
}
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);
+#line 1397
+ CError_ASSERT(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());
+#line 1568
+ CError_ASSERT(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;
+
+#line 1595
+ CError_ASSERT(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;
+ Object *obj;
+ SInt32 size;
+
+ CodeGen_InitialSanityCheck();
+ if (!saveheaperror) {
+ saveheaperror = getheaperror();
+ setheaperror(CodeGen_heaperror);
+ }
+
+ if (cparamblkptr->isPrecompiling == 1)
+ CError_Error(180);
+
+ if (!func) {
+ func = createstaticinitobject();
+ } else if (func && func->name) {
+ PrintProgressFunction(func->name->name);
+ }
+
+ 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);
+ if (copts.debuglisting)
+ DumpIR(statements, func);
+
+ if (copts.profile) {
+ makes_call = 1;
+ requires_frame = 1;
+ }
+
+ initpcode();
+
+ pclabel(prologue = makepcblock(), makepclabel());
+ prologue->flags |= fPCBlockFlag1;
+
+ 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_mode || copts.altivec_model)
+ branch_label(makepclabel());
+
+ load_TOC_pointers();
+
+ if (copts.profile)
+ callprofiler(CMangler_GetLinkName(func)->name);
+
+ assign_labels(*statements);
+ open_temp_registers();
+
+ for (stmt = *statements; 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, stmt->label);
+ break;
+ case ST_BEGINCATCH:
+ capturestackpointer(stmt->expr->data.objref);
+ break;
+ case ST_ENDCATCHDTOR:
+#line 2056
+ CError_ASSERT(stmt->expr->data.objref->datatype == DLOCAL);
+ obj = stmt->expr->data.objref;
+ add_immediate(3, local_base_register(obj), obj, 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) {
+ // ... will need to understand inline ASM properly for this ...
+ if (((WeirdInlineAsmThing *) stmt->expr)->x2 & 1) {
+#line 2076
+ CError_FATAL();
+ } else {
+ branch_label(makepclabel());
+ InlineAsm_TranslateIRtoPCode(stmt);
+ }
+ }
+ break;
+ case ST_BEGINLOOP:
+#line 2086
+ CError_FATAL();
+ break;
+ case ST_ENDLOOP:
+#line 2090
+ CError_FATAL();
+ break;
+ default:
+#line 2094
+ CError_FATAL();
+ }
+ check_temp_registers();
+ }
+
+ close_temp_registers();
+ labelstatement(returnlabel);
+
+ current_statement = NULL;
+
+ epilogue = pclastblock;
+ pclastblock->flags |= fPCBlockFlag2;
+
+ 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_mode == 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_mode == 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_mode) {
+ 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_mode) {
+ 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.isGeneratingDebugInfo;
+ save_peephole = copts.peephole;
+ save_traceback = copts.traceback;
+
+ CodeGen_InitialSanityCheck();
+#line 2270
+ CError_ASSERT(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.isGeneratingDebugInfo = 0;
+ copts.peephole = 0;
+ copts.traceback = 0;
+ assemblefunction(thunkobj, NULL);
+ copts.isGeneratingDebugInfo = 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();
}
-static void labelstatement() {}
-static void gotostatement() {}
-static void gotoexpression() {}
-static void conditionalstatement() {}
-static void returnstatement() {}
-static void capturestackpointer() {}
-static void resetstackpointer() {}
-static void callprofiler() {}
-static void exitprofiler() {}
-void CodeGen_Generator() {}
-void CodeGen_GenVDispatchThunk() {}
-void CodeGen_SetupRuntimeObjects() {}
-Boolean CodeGen_ReInitRuntimeObjects(Boolean is_precompiler) {}
-Boolean CodeGen_IsPublicRuntimeObject(Object *obj) {}
-void CodeGen_SOMStub() {}
-void CodeGen_ParseDeclSpec() {}
-static void CodeGen_EOLCheck() {}
-static void schedule_for() {}
-static void pragma_scheduling() {}
-static void CodeGen_ParseLongIntegerORonORoff() {}
-void CodeGen_ParsePragma(HashNameNode *name) {}
-void CodeGen_UpdateObject(Object *object) {}
-void CodeGen_UpdateBackEndOptions() {}
-void CodeGen_objc_method_self_offset() {}
-void CodeGen_objc_method_sel_offset() {}
-void CodeGen_objc_method_arg_offset() {}
-void CodeGen_objc_method_args_size() {}
-void CodeGen_HandleIntrinsicCall() {}
-void CodeGen_HandleTypeCast() {}
-void CodeGen_AssignCheck() {}
-void CodeGen_CollapseVectorExpression() {}
-void CodeGen_InsertSpecialMacros() {}
-char *CodeGen_ExpandSpecialMacro(Macro *macro) {}
-void CodeGen_reportheapinfo() {}
-static void CodeGen_heaperror() {}
-void CodeGen_InitialSanityCheck() {}
+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();
+ 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.isGeneratingDebugInfo;
+ save_peephole = copts.peephole;
+ save_traceback = copts.traceback;
+
+ CodeGen_InitialSanityCheck();
+ memclrw(&opnd, sizeof(Operand));
+#line 2528
+ CError_ASSERT(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) {
+#line 2562
+ CError_FATAL();
+ } 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.isGeneratingDebugInfo = 0;
+ copts.peephole = 0;
+ copts.traceback = 0;
+ assemblefunction(a, NULL);
+ copts.isGeneratingDebugInfo = 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(176);
+ }
+}
+
+static void CodeGen_EOLCheck(void) {
+ short t;
+
+ if (plex() != TK_NEG7) {
+ CPrep_Error(113);
+ do {
+ t = plex();
+ } while (t != TK_NEG7 && t != 0);
+ }
+}
+
+static void schedule_for(int what) {
+ CPrep_PushOption(OPT_OFFSET(schedule_cpu), what);
+ if (copts.schedule_mode == 0)
+ CPrep_PushOption(OPT_OFFSET(schedule_mode), 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(schedule_cpu));
+ CPrep_PopOption(OPT_OFFSET(schedule_mode));
+ return;
+ } else if (!strcmp(tkidentifier->name, "off")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_mode), 0);
+ return;
+ } else if (!strcmp(tkidentifier->name, "once")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_mode), 1);
+ return;
+ } else if (!strcmp(tkidentifier->name, "twice")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_mode), 2);
+ return;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ CPrep_PushOption(OPT_OFFSET(schedule_mode), 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(115);
+ return;
+ }
+ CPrep_Error(186);
+ 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(186);
+ return;
+ }
+ schedule_for(cpu);
+ return;
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+}
+
+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(154);
+ 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(186);
+ return 0;
+ } else {
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+ }
+
+ 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(186);
+ }
+ } 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ 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.ppc_unroll_speculative = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.ppc_unroll_speculative = 1;
+ } else {
+ CError_Error(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "ppc_unroll_instructions_limit")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ copts.ppc_unroll_instructions_limit = CInt64_GetULong(&tkintconst);
+ if (copts.ppc_unroll_instructions_limit < 0) {
+ copts.ppc_unroll_instructions_limit = 0;
+ CError_Error(186);
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.ppc_unroll_instructions_limit = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.ppc_unroll_instructions_limit = 70;
+ } else {
+ CError_Error(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ 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(186);
+ } else if (value > 255) {
+ copts.gen_fsel = 255;
+ CError_Error(186);
+ } 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "ppc_unroll_factor_limit")) {
+ t = plex();
+ if (t == TK_INTCONST) {
+ copts.ppc_unroll_factor_limit = CInt64_GetULong(&tkintconst);
+ if (copts.ppc_unroll_factor_limit < 0) {
+ copts.ppc_unroll_factor_limit = 0;
+ CError_Error(186);
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "off")) {
+ copts.ppc_unroll_factor_limit = 0;
+ } else if (!strcmp(tkidentifier->name, "on")) {
+ copts.ppc_unroll_factor_limit = 10;
+ } else {
+ CError_Error(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+ 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(code_alignment), value);
+ break;
+ default:
+ PPCError_Warning(161);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER && !strcmp(tkidentifier->name, "reset")) {
+ CPrep_PopOption(OPT_OFFSET(code_alignment));
+ } else {
+ PPCError_Warning(161);
+ }
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (!strcmp(name->name, "processor")) {
+ if (cscope_currentfunc) {
+ PPCError_Warning(156, "pragma processor");
+ return;
+ }
+ t = plex();
+ if (t == TK_INTCONST) {
+ switch (CInt64_GetULong(&tkintconst)) {
+ case 401:
+ copts.cpu = 0;
+ break;
+ case 403:
+ copts.cpu = 1;
+ break;
+ case 505:
+ copts.cpu = 2;
+ break;
+ case 509:
+ copts.cpu = 3;
+ break;
+ case 555:
+ copts.cpu = 4;
+ break;
+ case 556:
+ copts.cpu = 25;
+ break;
+ case 565:
+ copts.cpu = 26;
+ break;
+ case 601:
+ copts.cpu = 5;
+ break;
+ case 602:
+ copts.cpu = 6;
+ break;
+ case 8240:
+ copts.cpu = 18;
+ break;
+ case 8260:
+ copts.cpu = 19;
+ break;
+ case 603:
+ copts.cpu = 7;
+ break;
+ case 604:
+ copts.cpu = 9;
+ break;
+ case 740:
+ copts.cpu = 11;
+ break;
+ case 750:
+ copts.cpu = 12;
+ break;
+ case 801:
+ copts.cpu = 13;
+ break;
+ case 821:
+ copts.cpu = 14;
+ break;
+ case 823:
+ copts.cpu = 15;
+ break;
+ case 850:
+ copts.cpu = 16;
+ break;
+ case 860:
+ copts.cpu = 17;
+ break;
+ case 7400:
+ copts.cpu = 21;
+ break;
+ default:
+ PPCError_Warning(208);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "generic"))
+ copts.cpu = 20;
+ else if (!strcmp(tkidentifier->name, "603e"))
+ copts.cpu = 8;
+ else if (!strcmp(tkidentifier->name, "604e"))
+ copts.cpu = 10;
+ else if (!strcmp(tkidentifier->name, "PPC603e"))
+ copts.cpu = 8;
+ else if (!strcmp(tkidentifier->name, "PPC604e"))
+ copts.cpu = 10;
+ else
+ PPCError_Warning(208);
+ } else {
+ PPCError_Warning(208);
+ }
+
+ 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(some_alignment), value);
+ break;
+ default:
+ PPCError_Warning(191);
+ CodeGen_EOLCheck();
+ return;
+ }
+ } else if (t == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "reset"))
+ CPrep_PopOption(OPT_OFFSET(some_alignment));
+ else if (!strcmp(tkidentifier->name, "on"))
+ CPrep_PushOption(OPT_OFFSET(some_alignment), 4);
+ else if (!strcmp(tkidentifier->name, "off"))
+ CPrep_PushOption(OPT_OFFSET(some_alignment), 1);
+ } else {
+ PPCError_Warning(161);
+ }
+
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+
+ 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(189);
+ copts.codegen_pic = 0;
+ }
+ } else {
+ CError_Error(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+
+ 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(186);
+ return;
+ }
+ } else {
+ CError_Error(186);
+ }
+
+ 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(186);
+ }
+
+ CodeGen_EOLCheck();
+ return;
+ }
+
+ if (copts.warn_illpragma)
+ CPrep_Warning(186);
+
+ if (plex() != TK_NEG7) {
+ do {
+ t = plex();
+ } while (t != TK_NEG7 && 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.global_optimizer = 1;
+}
+
+void CodeGen_objc_method_self_offset() {
+ // TODO objc
+}
+
+void CodeGen_objc_method_sel_offset() {
+ // TODO objc
+}
+
+void CodeGen_objc_method_arg_offset() {
+ // TODO objc
+}
+
+void CodeGen_objc_method_args_size() {
+ // TODO objc
+}
+
+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_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_A:
+ case STRUCT_TYPE_B:
+ case STRUCT_TYPE_C:
+ case STRUCT_TYPE_D:
+ case STRUCT_TYPE_E:
+ expr = makemonadicnode(expr, ETYPCON);
+ expr->rtype = type;
+ expr->flags = flags;
+ return expr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+short CodeGen_AssignCheck(ENode *expr, Type *type, Boolean flag1, Boolean flag2) {
+ short result;
+ 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_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ if (i < 15) {
+ PPCError_Error(110, type, 0);
+ } else if (i > 15) {
+ PPCError_Error(111, 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(112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_4) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(113, 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_TYPE_4) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ vec->uc[0] = (UInt8) v.lo;
+ } else {
+ PPCError_Error(112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_E:
+ if (i < 7) {
+ PPCError_Error(110, type, 0);
+ } else if (i > 7) {
+ PPCError_Error(111, 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(112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_7 || TYPE_STRUCT(type)->stype == STRUCT_TYPE_E) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(113, 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_TYPE_7 || TYPE_STRUCT(type)->stype == STRUCT_TYPE_E) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ vec->us[0] = (UInt16) v.lo;
+ } else {
+ PPCError_Error(112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_TYPE_A:
+ case STRUCT_TYPE_B:
+ case STRUCT_TYPE_C:
+ if (i < 3) {
+ PPCError_Error(110, type, 0);
+ } else if (i > 3) {
+ PPCError_Error(111, 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(112);
+ break;
+ }
+
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_A) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(113, 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_TYPE_A) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ vec->ul[0] = v.lo;
+ } else {
+ PPCError_Error(112);
+ break;
+ }
+ result = 1;
+ }
+ break;
+
+ case STRUCT_TYPE_D:
+ if (i < 3) {
+ PPCError_Error(110, type, 0);
+ } else if (i > 3) {
+ PPCError_Error(111, 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(112);
+ 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(112);
+ 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_TYPE_4:
+ case STRUCT_TYPE_5:
+ case STRUCT_TYPE_6:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_4) {
+ if (!CInt64_IsInURange(v, 1))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 1))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ while (i < 16)
+ vec->uc[i++] = (UInt8) v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_TYPE_7:
+ case STRUCT_TYPE_8:
+ case STRUCT_TYPE_9:
+ case STRUCT_TYPE_E:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_7 || TYPE_STRUCT(type)->stype == STRUCT_TYPE_E) {
+ if (!CInt64_IsInURange(v, 2))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 2))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ while (i < 8)
+ vec->us[i++] = (UInt16) v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_TYPE_A:
+ case STRUCT_TYPE_B:
+ case STRUCT_TYPE_C:
+ {
+ CInt64 v = expr->data.intval;
+ if (copts.pedantic) {
+ if (TYPE_STRUCT(type)->stype == STRUCT_TYPE_A) {
+ if (!CInt64_IsInURange(v, 4))
+ PPCError_Warning(113, type, 0);
+ } else {
+ if (!CInt64_IsInRange(v, 4))
+ PPCError_Warning(113, type, 0);
+ }
+ }
+ while (i < 4)
+ vec->ul[i++] = v.lo;
+ result = 1;
+ break;
+ }
+ case STRUCT_TYPE_D:
+ {
+ Float fv;
+ if (!CInt64_IsInRange(expr->data.intval, 4)) {
+ PPCError_Error(112);
+ 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(112);
+ }
+ } else if (ENODE_IS(expr, EFLOATCONST)) {
+ switch (TYPE_STRUCT(type)->stype) {
+ default:
+ PPCError_Error(112);
+ break;
+ case STRUCT_TYPE_D:
+ {
+ 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(112);
+ } else if (!ENODE_IS(expr, EVECTOR128CONST)) {
+ PPCError_Error(112);
+ }
+
+ 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.align_mode == AlignMode2_PPC)
+ CPrep_InsertSpecialMacro(&alignM, "__NATURAL_ALIGNMENT__");
+
+ if (!copts.ANSI_strict)
+ 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.ANSI_strict && macro == &ppcM) return "1";
+ if (macro == &_ppc_M) return "1";
+
+#line 4801
+ CError_FATAL();
+ 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/unsorted/CodeGenOptPPC.c b/compiler_and_linker/unsorted/CodeGenOptPPC.c
new file mode 100644
index 0000000..5723395
--- /dev/null
+++ b/compiler_and_linker/unsorted/CodeGenOptPPC.c
@@ -0,0 +1,17 @@
+#include "compiler/CodeGenOptPPC.h"
+#include "compiler/InstrSelection.h"
+
+void CodeGen_InitCompiler(void) {
+ init_cgdispatch();
+}
+
+void CodeGen_TermCompiler(void) {
+
+}
+
+void CodeGen_InitBackEndOptions(void) {
+ // TODO
+}
+
+void Test_Version_Numbers(void) {
+}
diff --git a/compiler_and_linker/unsorted/CodeMotion.c b/compiler_and_linker/unsorted/CodeMotion.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CodeMotion.c
diff --git a/compiler_and_linker/unsorted/Coloring.c b/compiler_and_linker/unsorted/Coloring.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Coloring.c
diff --git a/compiler_and_linker/unsorted/ConstantPropagation.c b/compiler_and_linker/unsorted/ConstantPropagation.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/ConstantPropagation.c
diff --git a/compiler_and_linker/unsorted/CopyPropagation.c b/compiler_and_linker/unsorted/CopyPropagation.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/CopyPropagation.c
diff --git a/compiler_and_linker/unsorted/Exceptions.c b/compiler_and_linker/unsorted/Exceptions.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Exceptions.c
diff --git a/compiler_and_linker/unsorted/FuncLevelAsmPPC.c b/compiler_and_linker/unsorted/FuncLevelAsmPPC.c
new file mode 100644
index 0000000..d054191
--- /dev/null
+++ b/compiler_and_linker/unsorted/FuncLevelAsmPPC.c
@@ -0,0 +1,22 @@
+#include "compiler/FuncLevelAsmPPC.h"
+
+void setup_assembly_argument(Object *obj, short i) {
+}
+
+void assign_local_addresses() {
+}
+
+static void FuncAsm_PreScanDirectives() {
+}
+
+static void FuncAsm_AddEntryPoint() {
+}
+
+void Assembler() {
+}
+
+void SetupAssembler() {
+}
+
+void CleanupAssembler() {
+}
diff --git a/compiler_and_linker/unsorted/FunctionCalls.c b/compiler_and_linker/unsorted/FunctionCalls.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/FunctionCalls.c
diff --git a/compiler_and_linker/unsorted/GCCInlineAsm.c b/compiler_and_linker/unsorted/GCCInlineAsm.c
new file mode 100644
index 0000000..9bceb19
--- /dev/null
+++ b/compiler_and_linker/unsorted/GCCInlineAsm.c
@@ -0,0 +1,33 @@
+#include "compiler/GCCInlineAsm.h"
+
+Statement *first_ST_ASM;
+
+void InlineAsm_SkipComment() {
+}
+
+static void gcc_parse_attribute() {
+}
+
+static void gcc_parse_name() {
+}
+
+static void gcc_parse_expression() {
+}
+
+static void gcc_parse_input() {
+}
+
+static void gcc_parse_output() {
+}
+
+static void gcc_parse_killed() {
+}
+
+static void gcc_replace_arg_st_asm() {
+}
+
+static void gcc_replace_arg() {
+}
+
+void InlineAsm_gcc_parse(void) {
+}
diff --git a/compiler_and_linker/unsorted/GenStabs.c b/compiler_and_linker/unsorted/GenStabs.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/GenStabs.c
diff --git a/compiler_and_linker/unsorted/GlobalOptimizer.c b/compiler_and_linker/unsorted/GlobalOptimizer.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/GlobalOptimizer.c
diff --git a/compiler_and_linker/unsorted/IROUseDef.c b/compiler_and_linker/unsorted/IROUseDef.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IROUseDef.c
diff --git a/compiler_and_linker/unsorted/InlineAsm.c b/compiler_and_linker/unsorted/InlineAsm.c
new file mode 100644
index 0000000..ae73d91
--- /dev/null
+++ b/compiler_and_linker/unsorted/InlineAsm.c
@@ -0,0 +1,681 @@
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/GCCInlineAsm.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/CError.h"
+#include "compiler/CExpr.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInit.h"
+#include "compiler/CInline.h"
+#include "compiler/CInt64.h"
+#include "compiler/CMachine.h"
+#include "compiler/COptimizer.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/CScope.h"
+#include "compiler/PCode.h"
+#include "compiler/Registers.h"
+#include "compiler/objects.h"
+#include "compiler/scopes.h"
+#include "compiler/types.h"
+
+int allow_array_expressions = 1;
+
+int backtracking;
+jmp_buf backtrack;
+jmp_buf InlineAsm_assemblererror;
+static int ASMstmtnb;
+
+void AssemblerError(void) {
+ longjmp(InlineAsm_assemblererror, 1);
+}
+
+void InlineAsm_SyntaxError(short code) {
+ if (backtracking)
+ longjmp(backtrack, 1);
+
+ if (tk == TK_NEG7 || tk == ';')
+ code = CErrorStr112;
+ CError_Error(code);
+}
+
+CLabel *InlineAsm_LookupLabel(HashNameNode *name) {
+ CLabel *label;
+
+ for (label = Labels; label; label = label->next) {
+ if (name == label->name)
+ break;
+ }
+
+ return label;
+}
+
+CLabel *InlineAsm_DeclareLabel(HashNameNode *name) {
+ CLabel *label = newlabel();
+ label->name = name;
+ label->next = Labels;
+ Labels = label;
+ return label;
+}
+
+static void InlineAsm_DefineLabel(HashNameNode *name) {
+ CLabel *label;
+ Statement *stmt;
+
+ label = InlineAsm_LookupLabel(name);
+ if (!label) {
+ label = InlineAsm_DeclareLabel(name);
+ } else {
+ if (label->stmt)
+ CError_Error(CErrorStr171, name->name);
+ }
+
+ stmt = CFunc_AppendStatement(ST_LABEL);
+ stmt->label = label;
+ label->stmt = stmt;
+}
+
+Boolean InlineAsm_LookupSymbolOrTag(HashNameNode *name, IALookupResult *result, Boolean allow_tag) {
+ ObjBase *obj;
+ NameSpace *nspace;
+ NameSpaceObjectList *list;
+
+ result->name = name;
+ result->object = NULL;
+ result->label = NULL;
+ result->type = NULL;
+ result->has_value = 0;
+
+ if ((result->label = InlineAsm_LookupLabel(name)))
+ return 1;
+
+ for (nspace = cscope_current; nspace; nspace = nspace->parent) {
+ if ((list = CScope_FindName(nspace, name))) {
+ obj = list->object;
+ switch (obj->otype) {
+ case OT_ENUMCONST:
+ result->has_value = 1;
+ result->value = OBJ_ENUM_CONST(list->object)->val.lo;
+ return 1;
+ case OT_OBJECT:
+ if (OBJECT(obj)->datatype == DABSOLUTE) {
+ result->has_value = 1;
+ result->value = OBJECT(obj)->u.address;
+ } else {
+ if (OBJECT(obj)->datatype == DDATA && (OBJECT(obj)->qual & Q_10000))
+ CInit_ExportConst(OBJECT(obj));
+ result->object = OBJECT(obj);
+ }
+ return 1;
+ case OT_TYPE:
+ result->type = OBJ_TYPE(obj)->type;
+ return 1;
+ case OT_TYPETAG:
+ if (allow_tag) {
+ result->type = OBJ_TYPE_TAG(obj)->type;
+ return 1;
+ }
+ case OT_NAMESPACE:
+ case OT_MEMBERVAR:
+ return 0;
+ default:
+#line 245
+ CError_FATAL();
+ }
+ }
+ }
+
+ return 0;
+}
+
+Boolean InlineAsm_LookupSymbol(HashNameNode *name, IALookupResult *result) {
+ return InlineAsm_LookupSymbolOrTag(name, result, 0);
+}
+
+static ObjMemberVar *isclassmember(TypeClass *tclass, HashNameNode *name) {
+ NameSpaceObjectList *list;
+
+ list = CScope_FindName(tclass->nspace, name);
+ return (list && list->object->otype == OT_MEMBERVAR) ? OBJ_MEMBER_VAR(list->object) : NULL;
+}
+
+SInt32 InlineAsm_StructMemberOffset(Type *type) {
+ StructMember *member;
+ ObjMemberVar *ivar;
+ SInt32 offset = 0;
+
+ do {
+ if (IS_TYPE_STRUCT(type)) {
+ tk = lex();
+ if (tk != TK_IDENTIFIER)
+ InlineAsm_SyntaxError(CErrorStr107);
+ member = ismember(TYPE_STRUCT(type), tkidentifier);
+ if (!member)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset += member->offset;
+ type = member->type;
+ tk = lex();
+ } else if (IS_TYPE_CLASS(type)) {
+ tk = lex();
+ if (tk != TK_IDENTIFIER)
+ InlineAsm_SyntaxError(CErrorStr107);
+ ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
+ if (!ivar)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset += ivar->offset;
+ type = ivar->type;
+ tk = lex();
+ } else {
+ CError_Error(CErrorStr149);
+ }
+ } while (tk == '.');
+
+ return offset;
+}
+
+SInt32 InlineAsm_StructArrayMemberOffset(Type *type) {
+ StructMember *member;
+ ObjMemberVar *ivar;
+ SInt32 offset = 0;
+
+ do {
+ if (tk == '.') {
+ if (IS_TYPE_STRUCT(type)) {
+ tk = lex();
+ if (tk != TK_IDENTIFIER)
+ InlineAsm_SyntaxError(CErrorStr107);
+ member = ismember(TYPE_STRUCT(type), tkidentifier);
+ if (!member)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset += member->offset;
+ type = member->type;
+ tk = lex();
+ } else if (IS_TYPE_CLASS(type)) {
+ tk = lex();
+ if (tk != TK_IDENTIFIER)
+ InlineAsm_SyntaxError(CErrorStr107);
+ ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
+ if (!ivar)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset += ivar->offset;
+ type = ivar->type;
+ tk = lex();
+ } else {
+ CError_Error(CErrorStr149);
+ }
+ } else {
+ if (IS_TYPE_ARRAY(type)) {
+ type = TPTR_TARGET(type);
+ tk = lex();
+ offset += type->size * InlineAsm_ConstantExpression();
+ if (tk != ']')
+ InlineAsm_SyntaxError(125);
+ tk = lex();
+ } else {
+ CError_Error(CErrorStr148);
+ }
+ }
+ } while (tk == '.' || tk == '[');
+
+ return offset;
+}
+
+SInt32 InlineAsm_StructPointerMemberOffset(Type *type) {
+ StructMember *member;
+ ObjMemberVar *ivar;
+ SInt32 offset;
+
+ tk = lex();
+ if (tk != TK_IDENTIFIER)
+ InlineAsm_SyntaxError(107);
+
+ if (IS_TYPE_STRUCT(type)) {
+ member = ismember(TYPE_STRUCT(type), tkidentifier);
+ if (!member)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset = member->offset;
+ type = member->type;
+ } else {
+ ivar = isclassmember(TYPE_CLASS(type), tkidentifier);
+ if (!ivar)
+ CError_Error(CErrorStr150, tkidentifier->name);
+ offset = ivar->offset;
+ type = ivar->type;
+ }
+
+ tk = lex();
+ if (tk == '.' || tk == '[')
+ offset += InlineAsm_StructArrayMemberOffset(type);
+
+ return offset;
+}
+
+static SInt32 DiadicOperator(SInt32 left, short op, SInt32 right) {
+ CInt64 left64;
+ CInt64 right64;
+ CInt64_SetLong(&left64, left);
+ CInt64_SetLong(&right64, right);
+ right64 = CMach_CalcIntDiadic(TYPE(&stsignedint), left64, op, right64);
+ return CInt64_GetULong(&right64);
+}
+
+static SInt32 PrimaryExpression(void) {
+ IALookupResult result;
+ SInt32 value;
+
+ switch (tk) {
+ case TK_IDENTIFIER:
+ if (InlineAsm_LookupSymbol(tkidentifier, &result)) {
+ if (result.has_value) {
+ tk = lex();
+ return result.value;
+ }
+
+ if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) {
+ tk = lex();
+ if (tk != '.')
+ InlineAsm_SyntaxError(120);
+ if (allow_array_expressions)
+ return InlineAsm_StructArrayMemberOffset(result.type);
+ else
+ return InlineAsm_StructMemberOffset(result.type);
+ } else {
+ InlineAsm_SyntaxError(124);
+ }
+ } else {
+ InlineAsm_SyntaxError(124);
+ }
+ break;
+ case TK_INTCONST:
+ value = tkintconst.lo;
+ tk = lex();
+ return value;
+ case TK_SIZEOF:
+ return scansizeof();
+ case '+':
+ tk = lex();
+ return PrimaryExpression();
+ case '-':
+ tk = lex();
+ return -PrimaryExpression();
+ case '!':
+ tk = lex();
+ return PrimaryExpression() == 0;
+ case '~':
+ tk = lex();
+ return ~PrimaryExpression();
+ case '(':
+ tk = lex();
+ value = InlineAsm_ConstantExpression();
+ if (tk != ')')
+ InlineAsm_SyntaxError(115);
+ tk = lex();
+ return value;
+ default:
+ InlineAsm_SyntaxError(120);
+ }
+
+ return 0;
+}
+
+static SInt32 ConstantExpressionTail(SInt32 value) {
+ SInt32 right;
+ short left_token;
+ short right_prec;
+
+ while (1) {
+ left_token = tk;
+ tk = lex();
+ right = PrimaryExpression();
+
+ right_prec = GetPrec(tk);
+ if (right_prec == 0)
+ return DiadicOperator(value, left_token, right);
+
+ if (GetPrec(left_token) >= right_prec) {
+ value = DiadicOperator(value, left_token, right);
+ } else {
+ value = DiadicOperator(value, left_token, ConstantExpressionTail(right));
+ if (GetPrec(tk) == 0)
+ return value;
+ }
+ }
+}
+
+SInt32 InlineAsm_ConstantExpression(void) {
+ SInt32 value = PrimaryExpression();
+
+ if (GetPrec(tk) == 0)
+ return value;
+ else
+ return ConstantExpressionTail(value);
+}
+
+HashNameNode *MakeLocalLabel(CInt64 num) {
+ char buf[80];
+ sprintf(buf, "@%i_%i", ASMstmtnb, CInt64_GetULong(&num));
+ return GetHashNameNodeExport(buf);
+}
+
+static void ScanOptionalLabel() {
+ if (tk == TK_INTCONST) {
+ if (lookahead() == ':') {
+ InlineAsm_DefineLabel(MakeLocalLabel(tkintconst));
+ tk = lex();
+ tk = lex();
+ }
+ } else {
+ if (tkidentifier->name[0] == '@') {
+ InlineAsm_DefineLabel(tkidentifier);
+ tk = lex();
+ if (tk == ':')
+ tk = lex();
+ } else {
+ HashNameNode *name = tkidentifier;
+ short t = lookahead();
+ tkidentifier = name;
+ if (t == ':') {
+ InlineAsm_DefineLabel(name);
+ tk = lex();
+ tk = lex();
+ }
+ }
+ }
+}
+
+static void ScanStatements(volatile short endToken, UInt8 mode) {
+ if (setjmp(InlineAsm_assemblererror)) {
+ while (tk != TK_NEG7 && tk != endToken && tk != '}' && tk)
+ tk = lex();
+ if (tk == ';' || tk == TK_NEG7)
+ tk = lex();
+ } else {
+ InlineAsm_Initialize(mode);
+ InlineAsm_gccmode = 0;
+ if (setjmp(InlineAsm_assemblererror)) {
+ while (tk != ';' && tk != TK_NEG7 && tk != endToken && tk != '}' && tk)
+ tk = lex();
+ if (tk == ';' || tk == TK_NEG7)
+ tk = lex();
+ }
+
+ while (tk && tk != endToken) {
+ backtracking = 0;
+ sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset);
+ if (tk == '"') {
+ if (InlineAsm_gccmode) {
+ tk = lex();
+ InlineAsm_gcc_parse();
+ } else {
+ InlineAsm_gccmode = 1;
+ copts.cplusplus = 0;
+ copts.asmpoundcomment = 1;
+ tk = lex();
+ }
+ }
+
+ if (tk == '.') {
+ InlineAsm_ScanAssemblyDirective();
+ } else if (tk == TK_IDENTIFIER) {
+ ScanOptionalLabel();
+ if (tk == TK_IDENTIFIER)
+ InlineAsm_ScanAssemblyInstruction();
+ } else if (tk == TK_INTCONST) {
+ ScanOptionalLabel();
+ if (tk == TK_IDENTIFIER)
+ InlineAsm_ScanAssemblyInstruction();
+ }
+
+ if (InlineAsm_gccmode && tk == '"') {
+ tk = lex();
+ InlineAsm_gcc_parse();
+ }
+
+ if (tk == ';' || tk == TK_NEG7) {
+ CPrep_TokenStreamFlush();
+ tk = lex();
+ } else if (tk != endToken) {
+ if (endToken == ')')
+ CError_Error(CErrorStr115);
+ else
+ CError_Error(CErrorStr113);
+ }
+ }
+ }
+}
+
+void InlineAsm_ScanStatements(volatile short endToken) {
+ ScanStatements(endToken, 0);
+}
+
+void InlineAsm_ScanFunction(volatile short endToken) {
+ ScanStatements(endToken, 1);
+}
+
+void InlineAsm_Assemble(void) {
+ short token = (tk == '(') ? ')' : '}';
+ char save_pc = copts.asmpoundcomment;
+ char save_cpp = copts.cplusplus;
+
+ cprep_nostring = 1;
+ CFunc_AppendStatement(ST_NOP);
+ first_ST_ASM = curstmt;
+ ASMstmtnb++;
+
+ cprep_eoltokens = 1;
+ in_assembler = 1;
+ tk = lex();
+ InlineAsm_ScanStatements(token);
+ in_assembler = 0;
+ cprep_eoltokens = 0;
+ cprep_nostring = 0;
+
+ copts.asmpoundcomment = save_pc;
+ copts.cplusplus = save_cpp;
+}
+
+void InlineAsm_PackAsmStatement(Statement *stmt, Statement *first, void **output, SInt32 *outsize) {
+ InlineAsm *src;
+ InlineAsm *dest;
+ IAOperand *op;
+ SInt32 i;
+ SInt32 size;
+
+ src = (InlineAsm *) stmt->expr;
+ size = sizeof(InlineAsm) + sizeof(IAOperand) * src->argcount;
+ dest = galloc(size);
+ memcpy(dest, src, size);
+
+ for (i = 0, op = dest->args; i < dest->argcount; i++, op++) {
+ switch (op->type) {
+ case IAOpnd_0:
+ break;
+ case IAOpnd_Reg:
+ case IAOpnd_4:
+ op->u.reg.object = (Object *) CInline_GetLocalID(op->u.reg.object);
+ break;
+ case IAOpnd_Lab:
+ op->u.lab.label = (CLabel *) CInline_GetStatementNumber(first, op->u.lab.label->stmt);
+ break;
+ case IAOpnd_LabDiff:
+ op->u.labdiff.label1 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label1->stmt);
+ op->u.labdiff.label2 = (CLabel *) CInline_GetStatementNumber(first, op->u.labdiff.label2->stmt);
+ break;
+ }
+ }
+
+ *output = dest;
+ *outsize = size;
+}
+
+void InlineAsm_UnpackAsmStatement(Statement *stmt, CLabel **labelArray, Boolean flag, void *data, SInt32 size) {
+ InlineAsm *ia;
+ IAOperand *op;
+ SInt32 i;
+
+ ia = galloc(size);
+ memcpy(ia, data, size);
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ switch (op->type) {
+ case IAOpnd_0:
+ break;
+ case IAOpnd_Reg:
+ case IAOpnd_4:
+ op->u.reg.object = CInline_GetLocalObj((SInt32) op->u.reg.object, flag);
+ break;
+ case IAOpnd_Lab:
+ op->u.lab.label = labelArray[(SInt16) op->u.lab.label];
+ break;
+ case IAOpnd_LabDiff:
+ op->u.labdiff.label1 = labelArray[(SInt16) op->u.labdiff.label1];
+ op->u.labdiff.label2 = labelArray[(SInt16) op->u.labdiff.label2];
+ break;
+ }
+ }
+
+ stmt->expr = (ENode *) ia;
+}
+
+void InlineAsm_CheckLocalUsage(Statement *stmt) {
+ InlineAsm *ia = (InlineAsm *) stmt->expr;
+ IAOperand *op;
+ SInt32 i;
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ switch (op->type) {
+ case IAOpnd_Reg:
+ if (op->u.reg.object)
+ SetVarUsage(op->u.reg.object, 0);
+ break;
+ case IAOpnd_4:
+ SetVarUsage(op->u.obj.obj, 1);
+ break;
+ }
+ }
+}
+
+CLabel *InlineAsm_GetReferencedLabel(Statement *stmt) {
+ InlineAsm *ia = (InlineAsm *) stmt->expr;
+ IAOperand *op;
+ SInt32 i;
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ if (op->type == IAOpnd_Lab)
+ return op->u.lab.label;
+ if (op->type == IAOpnd_LabDiff)
+ return op->u.labdiff.label1;
+ }
+
+ return NULL;
+}
+
+CLabel *InlineAsm_GetReferencedLabel2(Statement *stmt) {
+ InlineAsm *ia = (InlineAsm *) stmt->expr;
+ IAOperand *op;
+ SInt32 i;
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ if (op->type == IAOpnd_LabDiff)
+ return op->u.labdiff.label2;
+ }
+
+ return NULL;
+}
+
+Object *InlineAsm_GetObjectOffset(InlineAsm *ia, SInt32 index, SInt32 *offset) {
+ IAOperand *op;
+ SInt32 i;
+ SInt32 counter;
+
+ for (i = 0, counter = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ if (op->type == IAOpnd_3) {
+ if (counter++ == index) {
+ *offset = ((SInt32) &op->u.obj.obj) - ((SInt32) ia);
+ return op->u.obj.obj;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+char *InlineAsm_DumpStatement(Statement *stmt) {
+ static char buffer[1024];
+ InlineAsm *ia;
+ IAOperand *arg;
+ int i;
+ char ch;
+ SInt32 offset;
+
+ ia = (InlineAsm *) stmt->expr;
+
+ strcpy(buffer, "\"");
+ strcat(buffer, InlineAsm_GetMnemonic(ia));
+ strcat(buffer, "\"");
+
+ for (i = 0, arg = ia->args; i < ia->argcount; i++, arg++) {
+ char argbuf[1024];
+
+ switch (arg->type) {
+ case IAOpnd_Imm:
+ sprintf(argbuf, " imm(%ld)", arg->u.imm.value);
+ break;
+ case IAOpnd_Reg:
+ ch = ' ';
+ if (arg->u.reg.effect & EffectWrite) {
+ if (arg->u.reg.effect & EffectRead)
+ ch = '+';
+ else
+ ch = '=';
+ } else {
+ if (!(arg->u.reg.effect & EffectRead))
+ ch = '0';
+ }
+
+ if (arg->u.reg.object) {
+ sprintf(argbuf,
+ "%creg(%s)",
+ ch,
+ arg->u.reg.object->name->name);
+ } else {
+ sprintf(argbuf,
+ "%creg(%s%d)",
+ ch,
+ register_class_name[arg->u.reg.rclass],
+ arg->u.reg.num);
+ }
+ break;
+
+ case IAOpnd_3:
+ case IAOpnd_4:
+ if (arg->u.obj.offset > 0)
+ sprintf(argbuf, " obj(%s+%ld)", arg->u.obj.obj->name->name, arg->u.obj.offset);
+ else if (arg->u.obj.offset < 0)
+ sprintf(argbuf, " obj(%s-%ld)", arg->u.obj.obj->name->name, -arg->u.obj.offset);
+ else
+ sprintf(argbuf, " obj(%s)", arg->u.obj.obj->name->name);
+ break;
+
+ case IAOpnd_Lab:
+ sprintf(argbuf, " lab(%s)", arg->u.lab.label->uniquename->name);
+ break;
+
+ case IAOpnd_LabDiff:
+ offset = !arg->negated ? 0 : arg->u.labdiff.offset;
+ sprintf(argbuf,
+ " labdiff(%s-%s%c%d)",
+ arg->u.labdiff.label1->uniquename->name,
+ arg->u.labdiff.label2->uniquename->name,
+ (arg->negated == 1) ? '-' : '+',
+ offset
+ );
+ break;
+ }
+
+ strcat(buffer, argbuf);
+ }
+
+ return buffer;
+}
diff --git a/compiler_and_linker/unsorted/InlineAsmMnemonicsPPC.c b/compiler_and_linker/unsorted/InlineAsmMnemonicsPPC.c
new file mode 100644
index 0000000..07d7d2c
--- /dev/null
+++ b/compiler_and_linker/unsorted/InlineAsmMnemonicsPPC.c
@@ -0,0 +1,1036 @@
+#include "compiler/InlineAsmMnemonicsPPC.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/CompilerTools.h"
+
+static IAMnemonic mnemonics[] = {
+ "abs", 0x000001A7, "=r,r", 0x00000001, 0x7C0002D0,
+ "abs.", 0x000001A7, "=r,r;=Z", 0x00000001, 0x7C0002D1,
+ "abso", 0x000001A7, "=r,r;+X", 0x00000001, 0x7C0006D0,
+ "abso.", 0x000001A7, "=r,r;+X=Z", 0x00000001, 0x7C0006D1,
+ "add", 0x0000003C, "=r,r,r", 0x000FFFFF, 0x7C000214,
+ "add.", 0x0000003C, "=r,r,r;=Z", 0x000FFFFF, 0x7C000215,
+ "addo", 0x0000003C, "=r,r,r;+X", 0x000FFFFF, 0x7C000614,
+ "addo.", 0x0000003C, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000615,
+ "addc", 0x0000003D, "=r,r,r;+X", 0x000FFFFF, 0x7C000014,
+ "addc.", 0x0000003D, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000015,
+ "addco", 0x0000003D, "=r,r,r;+X", 0x000FFFFF, 0x7C000414,
+ "addco.", 0x0000003D, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000415,
+ "adde", 0x0000003E, "=r,r,r;+X", 0x000FFFFF, 0x7C000114,
+ "adde.", 0x0000003E, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000115,
+ "addeo", 0x0000003E, "=r,r,r;+X", 0x000FFFFF, 0x7C000514,
+ "addeo.", 0x0000003E, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000515,
+ "addi", 0x0000003F, "=r,b,m;p", 0x000FFFFF, 0x38000000,
+ "addic", 0x00000040, "=r,r,i;+X", 0x000FFFFF, 0x30000000,
+ "addic.", 0x00000041, "=r,r,i;+X=Z", 0x000FFFFF, 0x34000000,
+ "addis", 0x00000042, "=r,b,M", 0x000FFFFF, 0x3C000000,
+ "addme", 0x00000043, "=r,r;+X", 0x000FFFFF, 0x7C0001D4,
+ "addme.", 0x00000043, "=r,r;+X=Z", 0x000FFFFF, 0x7C0001D5,
+ "addmeo", 0x00000043, "=r,r;+X", 0x000FFFFF, 0x7C0005D4,
+ "addmeo.", 0x00000043, "=r,r;+X=Z", 0x000FFFFF, 0x7C0005D5,
+ "addze", 0x00000044, "=r,r;+X", 0x000FFFFF, 0x7C000194,
+ "addze.", 0x00000044, "=r,r;+X=Z", 0x000FFFFF, 0x7C000195,
+ "addzeo", 0x00000044, "=r,r;+X", 0x000FFFFF, 0x7C000594,
+ "addzeo.", 0x00000044, "=r,r;+X=Z", 0x000FFFFF, 0x7C000595,
+ "and", 0x0000005C, "=r,r,r", 0x000FFFFF, 0x7C000038,
+ "and.", 0x0000005C, "=r,r,r;=Z", 0x000FFFFF, 0x7C000039,
+ "andc", 0x00000062, "=r,r,r", 0x000FFFFF, 0x7C000078,
+ "andc.", 0x00000062, "=r,r,r;=Z", 0x000FFFFF, 0x7C000079,
+ "andi.", 0x00000056, "=r,r,x;=Z", 0x000FFFFF, 0x70000000,
+ "andis.", 0x00000057, "=r,r,x;=Z", 0x000FFFFF, 0x74000000,
+ "b", 0x00000000, "l;p", 0x000FFFFF, 0x48000000,
+ "ba", 0x00000000, "l;p", 0x000FFFFF, 0x48000002,
+ "bc", 0x00000002, "B,Q,l;p", 0x000FFFFF, 0x40000000,
+ "bca", 0x00000002, "B,Q,l;p", 0x000FFFFF, 0x40000002,
+ "bcla", 0x00000002, "B,Q,l;=L", 0x000FFFFF, 0x40000003,
+ "bcctr", 0x00000004, "B,Q;Cp", 0x000FFFFF, 0x4C000420,
+ "bcctrl", 0x00000004, "B,Q;C=L", 0x000FFFFF, 0x4C000421,
+ "bcl", 0x00000002, "B,Q,l;=L", 0x000FFFFF, 0x40000001,
+ "bclr", 0x00000003, "B,Q;L", 0x000FFFFF, 0x4C000020,
+ "bclrl", 0x00000003, "B,Q;+L", 0x000FFFFF, 0x4C000021,
+ "bl", 0x00000001, "l;=L", 0x000FFFFF, 0x48000001,
+ "bla", 0x00000001, "l;=L", 0x000FFFFF, 0x48000003,
+ "clcs", 0x000001A8, "=r,r", 0x00000001, 0x7C000426,
+ "cmp", 0x00000053, "=?c,Or,r", 0x000FFFFF, 0x7C000000,
+ "cmpi", 0x00000052, "=?c,Or,i", 0x000FFFFF, 0x2C000000,
+ "cmpl", 0x00000055, "=?c,Or,r", 0x000FFFFF, 0x7C000040,
+ "cmpli", 0x00000054, "=?c,Or,u", 0x000FFFFF, 0x28000000,
+ "cntlzw", 0x00000066, "=r,r", 0x000FFFFF, 0x7C000034,
+ "cntlzw.", 0x00000066, "=r,r;=Z", 0x000FFFFF, 0x7C000035,
+ "crand", 0x0000006E, "=Q,Q,Q", 0x000FFFFF, 0x4C000202,
+ "crandc", 0x0000006F, "=Q,Q,Q", 0x000FFFFF, 0x4C000102,
+ "creqv", 0x00000070, "=Q,Q,Q", 0x000FFFFF, 0x4C000242,
+ "crnand", 0x00000071, "=Q,Q,Q", 0x000FFFFF, 0x4C0001C2,
+ "crnor", 0x00000072, "=Q,Q,Q", 0x000FFFFF, 0x4C000042,
+ "cror", 0x00000073, "=Q,Q,Q", 0x000FFFFF, 0x4C000382,
+ "crorc", 0x00000074, "=Q,Q,Q", 0x000FFFFF, 0x4C000342,
+ "crxor", 0x00000075, "=Q,Q,Q", 0x000FFFFF, 0x4C000182,
+ "dcbf", 0x00000037, "b,r", 0x080FFFFF, 0x7C0000AC,
+ "dcbst", 0x00000038, "b,r", 0x080FFFFF, 0x7C00006C,
+ "dcbt", 0x00000039, "b,r", 0x080FFFFF, 0x7C00022C,
+ "dcbtst", 0x0000003A, "b,r", 0x080FFFFF, 0x7C0001EC,
+ "dcba", 0x000000EB, "b,r", 0x00004000, 0x7C0005EC,
+ "dcbz", 0x0000003B, "b,r", 0x080FFFFF, 0x7C0007EC,
+ "dccci", 0x000000DE, "b,r", 0x000007C0, 0x7C00038C,
+ "dcread", 0x000000DF, "=r,(b,r)", 0x000007C0, 0x7C0003CC,
+ "dcbi", 0x000000C3, "b,r", 0x080FFFFF, 0x7C0003AC,
+ "icbi", 0x000000C4, "b,r", 0x000FEFFF, 0x7C0007AC,
+ "icbt", 0x000000E0, "b,r", 0x000007C0, 0x7C00020C,
+ "iccci", 0x000000E1, "b,r", 0x000007C0, 0x7C00078C,
+ "icread", 0x000000E2, "b,r", 0x000007C0, 0x7C0007CC,
+ "div", 0x000001A2, "=r,r,r", 0x00000001, 0x7C000296,
+ "div.", 0x000001A2, "=r,r,r;=Z", 0x00000001, 0x7C000297,
+ "divo", 0x000001A2, "=r,r,r;+X", 0x00000001, 0x7C000696,
+ "divo.", 0x000001A2, "=r,r,r;+X=Z", 0x00000001, 0x7C000697,
+ "divs", 0x000001A3, "=r,r,r", 0x00000001, 0x7C0002D6,
+ "divs.", 0x000001A3, "=r,r,r;=Z", 0x00000001, 0x7C0002D7,
+ "divso", 0x000001A3, "=r,r,r;+X", 0x00000001, 0x7C0006D6,
+ "divso.", 0x000001A3, "=r,r,r;+X=Z", 0x00000001, 0x7C0006D7,
+ "divw", 0x00000045, "=r,r,r", 0x000FFFFF, 0x7C0003D6,
+ "divw.", 0x00000045, "=r,r,r;=Z", 0x000FFFFF, 0x7C0003D7,
+ "divwo", 0x00000045, "=r,r,r;+X", 0x000FFFFF, 0x7C0007D6,
+ "divwo.", 0x00000045, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C0007D7,
+ "divwu", 0x00000046, "=r,r,r", 0x000FFFFF, 0x7C000396,
+ "divwu.", 0x00000046, "=r,r,r;=Z", 0x000FFFFF, 0x7C000397,
+ "divwuo", 0x00000046, "=r,r,r;+X", 0x000FFFFF, 0x7C000796,
+ "divwuo.", 0x00000046, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000797,
+ "doz", 0x000001A4, "=r,r,r", 0x00000001, 0x7C000210,
+ "doz.", 0x000001A4, "=r,r,r;=Z", 0x00000001, 0x7C000211,
+ "dozo", 0x000001A4, "=r,r,r;+X", 0x00000001, 0x7C000610,
+ "dozo.", 0x000001A4, "=r,r,r;+X=Z", 0x00000001, 0x7C000611,
+ "dozi", 0x000001A9, "=r,r,x", 0x00000001, 0x24000000,
+ "dsa", 0x000000DC, "", 0x00000002, 0x7C0004E8,
+ "esa", 0x000000DD, "", 0x00000002, 0x7C0004A8,
+ "eciwx", 0x000000C1, "=r,(b,r)", 0x020FFFFF, 0x7C00026C,
+ "ecowx", 0x000000C2, "r,(b,r)", 0x020FFFFF, 0x7C00036C,
+ "eieio", 0x00000085, "", 0x000FFFFF, 0x7C0006AC,
+ "eqv", 0x00000061, "=r,r,r", 0x000FFFFF, 0x7C000238,
+ "eqv.", 0x00000061, "=r,r,r;=Z", 0x000FFFFF, 0x7C000239,
+ "extsb", 0x00000064, "=r,r", 0x000FFFFF, 0x7C000774,
+ "extsb.", 0x00000064, "=r,r;=Z", 0x000FFFFF, 0x7C000775,
+ "extsh", 0x00000065, "=r,r", 0x000FFFFF, 0x7C000734,
+ "extsh.", 0x00000065, "=r,r;=Z", 0x000FFFFF, 0x7C000735,
+ "fabs", 0x0000009F, "=f,f", 0x800FFFFF, 0xFC000210,
+ "fabs.", 0x0000009F, "=f,f;=Z", 0x800FFFFF, 0xFC000211,
+ "fadd", 0x000000A2, "=f,f,f", 0x800FFFFF, 0xFC00002A,
+ "fadd.", 0x000000A2, "=f,f,f;=Z", 0x800FFFFF, 0xFC00002B,
+ "fadds", 0x000000A3, "=f,f,f", 0x800FFFFF, 0xEC00002A,
+ "fadds.", 0x000000A3, "=f,f,f;=Z", 0x800FFFFF, 0xEC00002B,
+ "fcmpo", 0x000000B9, "=?c,f,f", 0x800FFFFF, 0xFC000040,
+ "fcmpu", 0x000000B8, "=?c,f,f", 0x800FFFFF, 0xFC000000,
+ "fctiw", 0x000000B6, "=f,f", 0x800FFFFF, 0xFC00001C,
+ "fctiw.", 0x000000B6, "=f,f;=Z", 0x800FFFFF, 0xFC00001D,
+ "fctiwz", 0x000000B7, "=f,f", 0x800FFFFF, 0xFC00001E,
+ "fctiwz.", 0x000000B7, "=f,f;=Z", 0x800FFFFF, 0xFC00001F,
+ "fdiv", 0x000000A8, "=f,f,f", 0x800FFFFF, 0xFC000024,
+ "fdiv.", 0x000000A8, "=f,f,f;=Z", 0x800FFFFF, 0xFC000025,
+ "fdivs", 0x000000A9, "=f,f,f", 0x800FFFFF, 0xEC000024,
+ "fdivs.", 0x000000A9, "=f,f,f;=Z", 0x800FFFFF, 0xEC000025,
+ "fmadd", 0x000000AA, "=f,f,f,f", 0x800FFFFF, 0xFC00003A,
+ "fmadd.", 0x000000AA, "=f,f,f,f;=Z", 0x800FFFFF, 0xFC00003B,
+ "fmadds", 0x000000AB, "=f,f,f,f", 0x800FFFFF, 0xEC00003A,
+ "fmadds.", 0x000000AB, "=f,f,f,f;=Z", 0x800FFFFF, 0xEC00003B,
+ "fmr", 0x0000009E, "=f,f", 0x800FFFFF, 0xFC000090,
+ "fmr.", 0x0000009E, "=f,f;=Z", 0x800FFFFF, 0xFC000091,
+ "fmsub", 0x000000AC, "=f,f,f,f", 0x800FFFFF, 0xFC000038,
+ "fmsub.", 0x000000AC, "=f,f,f,f;=Z", 0x800FFFFF, 0xFC000039,
+ "fmsubs", 0x000000AD, "=f,f,f,f", 0x800FFFFF, 0xEC000038,
+ "fmsubs.", 0x000000AD, "=f,f,f,f;=Z", 0x800FFFFF, 0xEC000039,
+ "fmul", 0x000000A6, "=f,f,f", 0x800FFFFF, 0xFC000032,
+ "fmul.", 0x000000A6, "=f,f,f;=Z", 0x800FFFFF, 0xFC000033,
+ "fmuls", 0x000000A7, "=f,f,f", 0x800FFFFF, 0xEC000032,
+ "fmuls.", 0x000000A7, "=f,f,f;=Z", 0x800FFFFF, 0xEC000033,
+ "fnabs", 0x000000A1, "=f,f", 0x800FFFFF, 0xFC000110,
+ "fnabs.", 0x000000A1, "=f,f;=Z", 0x800FFFFF, 0xFC000111,
+ "fneg", 0x000000A0, "=f,f", 0x800FFFFF, 0xFC000050,
+ "fneg.", 0x000000A0, "=f,f;=Z", 0x800FFFFF, 0xFC000051,
+ "fnmadd", 0x000000AE, "=f,f,f,f", 0x800FFFFF, 0xFC00003E,
+ "fnmadd.", 0x000000AE, "=f,f,f,f;=Z", 0x800FFFFF, 0xFC00003F,
+ "fnmadds", 0x000000AF, "=f,f,f,f", 0x800FFFFF, 0xEC00003E,
+ "fnmadds.", 0x000000AF, "=f,f,f,f;=Z", 0x800FFFFF, 0xEC00003F,
+ "fnmsub", 0x000000B0, "=f,f,f,f", 0x800FFFFF, 0xFC00003C,
+ "fnmsub.", 0x000000B0, "=f,f,f,f;=Z", 0x800FFFFF, 0xFC00003D,
+ "fnmsubs", 0x000000B1, "=f,f,f,f", 0x800FFFFF, 0xEC00003C,
+ "fnmsubs.", 0x000000B1, "=f,f,f,f;=Z", 0x800FFFFF, 0xEC00003D,
+ "fres", 0x000000B2, "=f,f", 0x808FFFFF, 0xEC000030,
+ "fres.", 0x000000B2, "=f,f;=Z", 0x808FFFFF, 0xEC000031,
+ "frsp", 0x000000B5, "=f,f", 0x800FFFFF, 0xFC000018,
+ "frsp.", 0x000000B5, "=f,f;=Z", 0x800FFFFF, 0xFC000019,
+ "frsqrte", 0x000000B3, "=f,f", 0x808FFFFF, 0xFC000034,
+ "frsqrte.", 0x000000B3, "=f,f;=Z", 0x808FFFFF, 0xFC000035,
+ "fsel", 0x000000B4, "=f,f,f,f", 0x808FFFFF, 0xFC00002E,
+ "fsel.", 0x000000B4, "=f,f,f,f;=Z", 0x808FFFFF, 0xFC00002F,
+ "fsqrt", 0x000000D0, "=f,f", 0x80000000, 0xFC00002C,
+ "fsqrt.", 0x000000D0, "=f,f;=Z", 0x80000000, 0xFC00002D,
+ "fsqrts", 0x000000D1, "=f,f", 0x80000000, 0xEC00002C,
+ "fsqrts.", 0x000000D1, "=f,f;=Z", 0x80000000, 0xEC00002D,
+ "fsub", 0x000000A4, "=f,f,f", 0x800FFFFF, 0xFC000028,
+ "fsub.", 0x000000A4, "=f,f,f;=Z", 0x800FFFFF, 0xFC000029,
+ "fsubs", 0x000000A5, "=f,f,f", 0x800FFFFF, 0xEC000028,
+ "fsubs.", 0x000000A5, "=f,f,f;=Z", 0x800FFFFF, 0xEC000029,
+ "isync", 0x00000086, "", 0x000FFFFF, 0x4C00012C,
+ "lbz", 0x00000015, "=r,d(b)", 0x000FFFFF, 0x88000000,
+ "lbzu", 0x00000016, "=r,d(+b)", 0x000FFFFF, 0x8C000000,
+ "lbzx", 0x00000017, "=r,(b,r)", 0x000FFFFF, 0x7C0000AE,
+ "lbzux", 0x00000018, "=r,(+b,r)", 0x000FFFFF, 0x7C0000EE,
+ "lfd", 0x00000092, "=f,d(b)", 0x800FFFFF, 0xC8000000,
+ "lfdu", 0x00000093, "=f,d(+b)", 0x800FFFFF, 0xCC000000,
+ "lfdx", 0x00000094, "=f,(b,r)", 0x800FFFFF, 0x7C0004AE,
+ "lfdux", 0x00000095, "=f,(+b,r)", 0x800FFFFF, 0x7C0004EE,
+ "lfs", 0x0000008E, "=f,d(b)", 0x800FFFFF, 0xC0000000,
+ "lfsu", 0x0000008F, "=f,d(+b)", 0x800FFFFF, 0xC4000000,
+ "lfsx", 0x00000090, "=f,(b,r)", 0x800FFFFF, 0x7C00042E,
+ "lfsux", 0x00000091, "=f,(+b,r)", 0x800FFFFF, 0x7C00046E,
+ "lha", 0x0000001D, "=r,d(b)", 0x000FFFFF, 0xA8000000,
+ "lhau", 0x0000001E, "=r,d(+b)", 0x000FFFFF, 0xAC000000,
+ "lhaux", 0x00000020, "=r,(+b,r)", 0x000FFFFF, 0x7C0002EE,
+ "lhax", 0x0000001F, "=r,(b,r)", 0x000FFFFF, 0x7C0002AE,
+ "lhbrx", 0x00000021, "=r,(b,r)", 0x000FFFFF, 0x7C00062C,
+ "lhz", 0x00000019, "=r,d(b)", 0x000FFFFF, 0xA0000000,
+ "lhzu", 0x0000001A, "=r,d(+b)", 0x000FFFFF, 0xA4000000,
+ "lhzux", 0x0000001C, "=r,(+b,r)", 0x000FFFFF, 0x7C00026E,
+ "lhzx", 0x0000001B, "=r,(b,r)", 0x000FFFFF, 0x7C00022E,
+ "lmw", 0x00000027, "=r,d(b)", 0x000FFFFF, 0xB8000000,
+ "lscbx", 0x000001A1, "=r,(b,r)", 0x00000001, 0x7C00022A,
+ "lscbx.", 0x000001A1, "=r,(b,r);=Z", 0x00000001, 0x7C00022B,
+ "lswi", 0x000000BB, "=r,b,N", 0x000FFFFF, 0x7C0004AA,
+ "lswx", 0x000000BC, "=r,(b,r)", 0x000FFFFF, 0x7C00042A,
+ "lwarx", 0x000000BA, "=r,(b,r)", 0x000FFFFF, 0x7C000028,
+ "lwbrx", 0x00000026, "=r,(b,r)", 0x000FFFFF, 0x7C00042C,
+ "lwz", 0x00000022, "=r,d(b)", 0x000FFFFF, 0x80000000,
+ "lwzu", 0x00000023, "=r,d(+b)", 0x000FFFFF, 0x84000000,
+ "lwzux", 0x00000025, "=r,(+b,r)", 0x000FFFFF, 0x7C00006E,
+ "lwzx", 0x00000024, "=r,(b,r)", 0x000FFFFF, 0x7C00002E,
+ "maskg", 0x0000019F, "=r,r,r", 0x00000001, 0x7C00003A,
+ "maskg.", 0x0000019F, "=r,r,r;=Z", 0x00000001, 0x7C00003B,
+ "maskir", 0x000001A0, "=r,r,r", 0x00000001, 0x7C00043A,
+ "maskir.", 0x000001A0, "=r,r,r;=Z", 0x00000001, 0x7C00043B,
+ "mcrf", 0x00000076, "=c,c", 0x000FFFFF, 0x4C000000,
+ "mcrfs", 0x000000C5, "=c,x3", 0x800FFFFF, 0xFC000080,
+ "mcrxr", 0x000000C6, "=c;+X", 0x000FFFFF, 0x7C000400,
+ "mfcr", 0x00000082, "=r;Y", 0x000FFFFF, 0x7C000026,
+ "mfdcr", 0x000000E9, "=r,D", 0x000007C0, 0x7C000286,
+ "mffs", 0x00000083, "=f", 0x800FFFFF, 0xFC00048E,
+ "mffs.", 0x00000083, "=f;=Z", 0x800FFFFF, 0xFC00048F,
+ "mfmsr", 0x0000007D, "=r", 0x000FFFFF, 0x7C0000A6,
+ "mfrom", 0x000000DB, "=r,r", 0x00000002, 0x7C000212,
+ "mfspr", 0x0000007E, "=r,s", 0x000FFFFF, 0x7C0002A6,
+ "mfsr", 0x000000C8, "=r,u4", 0x010FFFFF, 0x7C0004A6,
+ "mfsrin", 0x000000CA, "=r,r", 0x010FFFFF, 0x7C000526,
+ "mtcrf", 0x0000007A, "x8,r;=Y", 0x000FFFFF, 0x7C000120,
+ "mtdcr", 0x000000EA, "D,r", 0x000007C0, 0x7C000386,
+ "mtfsb0", 0x000000CC, "u5", 0x000FFFFF, 0xFC00008C,
+ "mtfsb0.", 0x000000CC, "u5;=Z", 0x000FFFFF, 0xFC00008D,
+ "mtfsb1", 0x000000CD, "u5", 0x000FFFFF, 0xFC00004C,
+ "mtfsb1.", 0x000000CD, "u5;=Z", 0x000FFFFF, 0xFC00004D,
+ "mtfsf", 0x00000084, "x8,f", 0x800FFFFF, 0xFC00058E,
+ "mtfsf.", 0x00000084, "x8,f;=Z", 0x800FFFFF, 0xFC00058F,
+ "mtfsfi", 0x000000CE, "c,x4", 0x000FFFFF, 0xFC00010C,
+ "mtfsfi.", 0x000000CE, "c,x4;=Z", 0x000FFFFF, 0xFC00010D,
+ "mtmsr", 0x0000007B, "r", 0x000FFFFF, 0x7C000124,
+ "mtspr", 0x0000007C, "=s,r", 0x000FFFFF, 0x7C0003A6,
+ "mtsr", 0x000000C9, "u4,r", 0x010FFFFF, 0x7C0001A4,
+ "mtsrin", 0x000000CB, "r,r", 0x010FFFFF, 0x7C0001E4,
+ "mul", 0x000001A5, "=r,r,r", 0x00000001, 0x7C0000D6,
+ "mul.", 0x000001A5, "=r,r,r;=Z", 0x00000001, 0x7C0000D7,
+ "mulo", 0x000001A5, "=r,r,r;+X", 0x00000001, 0x7C0004D6,
+ "mulo.", 0x000001A5, "=r,r,r;+X=Z", 0x00000001, 0x7C0004D7,
+ "mulhw", 0x00000047, "=r,r,r", 0x000FFFFF, 0x7C000096,
+ "mulhw.", 0x00000047, "=r,r,r;=Z", 0x000FFFFF, 0x7C000097,
+ "mulhwu", 0x00000048, "=r,r,r", 0x000FFFFF, 0x7C000016,
+ "mulhwu.", 0x00000048, "=r,r,r;=Z", 0x000FFFFF, 0x7C000017,
+ "mulli", 0x00000049, "=r,r,i", 0x000FFFFF, 0x1C000000,
+ "mullw", 0x0000004A, "=r,r,r", 0x000FFFFF, 0x7C0001D6,
+ "mullw.", 0x0000004A, "=r,r,r;=Z", 0x000FFFFF, 0x7C0001D7,
+ "mullwo", 0x0000004A, "=r,r,r;+X", 0x000FFFFF, 0x7C0005D6,
+ "mullwo.", 0x0000004A, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C0005D7,
+ "nabs", 0x000001A6, "=r,r", 0x00000001, 0x7C0003D0,
+ "nabs.", 0x000001A6, "=r,r;=Z", 0x00000001, 0x7C0003D1,
+ "nabso", 0x000001A6, "=r,r;+X", 0x00000001, 0x7C0007D0,
+ "nabso.", 0x000001A6, "=r,r;+X=Z", 0x00000001, 0x7C0007D1,
+ "nand", 0x0000005F, "=r,r,r", 0x000FFFFF, 0x7C0003B8,
+ "nand.", 0x0000005F, "=r,r,r;=Z", 0x000FFFFF, 0x7C0003B9,
+ "neg", 0x0000004B, "=r,r", 0x000FFFFF, 0x7C0000D0,
+ "neg.", 0x0000004B, "=r,r;=Z", 0x000FFFFF, 0x7C0000D1,
+ "nego", 0x0000004B, "=r,r;+X", 0x000FFFFF, 0x7C0004D0,
+ "nego.", 0x0000004B, "=r,r;+X=Z", 0x000FFFFF, 0x7C0004D1,
+ "nor", 0x00000060, "=r,r,r", 0x000FFFFF, 0x7C0000F8,
+ "nor.", 0x00000060, "=r,r,r;=Z", 0x000FFFFF, 0x7C0000F9,
+ "or", 0x0000005D, "=r,r,r;pp", 0x000FFFFF, 0x7C000378,
+ "or.", 0x0000005D, "=r,r,r;pp=Z", 0x000FFFFF, 0x7C000379,
+ "orc", 0x00000063, "=r,r,r", 0x000FFFFF, 0x7C000338,
+ "orc.", 0x00000063, "=r,r,r;=Z", 0x000FFFFF, 0x7C000339,
+ "ori", 0x00000058, "=r,r,m", 0x000FFFFF, 0x60000000,
+ "oris", 0x00000059, "=r,r,M", 0x000FFFFF, 0x64000000,
+ "rfci", 0x000000E3, "", 0x000007C0, 0x4C000066,
+ "rfi", 0x00000088, "", 0x000FFFFF, 0x4C000064,
+ "rlmi", 0x000001AA, "+r,r,r,u5,u5", 0x00000001, 0x58000000,
+ "rlmi.", 0x000001AA, "+r,r,r,u5,u5;=Z", 0x00000001, 0x58000001,
+ "rlwimi", 0x00000069, "+r,r,u5,u5,u5", 0x000FFFFF, 0x50000000,
+ "rlwimi.", 0x00000069, "+r,r,u5,u5,u5;=Z", 0x000FFFFF, 0x50000001,
+ "rlwinm", 0x00000067, "=r,r,u5,u5,u5", 0x000FFFFF, 0x54000000,
+ "rlwinm.", 0x00000067, "=r,r,u5,u5,u5;=Z", 0x000FFFFF, 0x54000001,
+ "rlwnm", 0x00000068, "=r,r,r,u5,u5", 0x000FFFFF, 0x5C000000,
+ "rlwnm.", 0x00000068, "=r,r,r,u5,u5;=Z", 0x000FFFFF, 0x5C000001,
+ "rrib", 0x000001AB, "=r,r,r", 0x00000001, 0x7C000432,
+ "rrib.", 0x000001AB, "=r,r,r;=Z", 0x00000001, 0x7C000433,
+ "sc", 0x000000CF, "", 0x000FFFFF, 0x44000002,
+ "sle", 0x00000190, "=r,r,r", 0x00000001, 0x7C000132,
+ "sle.", 0x00000190, "=r,r,r;=Z", 0x00000001, 0x7C000133,
+ "sleq", 0x00000191, "=r,r,r", 0x00000001, 0x7C0001B2,
+ "sleq.", 0x00000191, "=r,r,r;=Z", 0x00000001, 0x7C0001B3,
+ "sliq", 0x00000192, "=r,r,u5", 0x00000001, 0x7C000170,
+ "sliq.", 0x00000192, "=r,r,u5;=Z", 0x00000001, 0x7C000171,
+ "slliq", 0x00000193, "=r,r,u5", 0x00000001, 0x7C0001F0,
+ "slliq.", 0x00000193, "=r,r,u5;=Z", 0x00000001, 0x7C0001F1,
+ "sllq", 0x00000194, "=r,r,r", 0x00000001, 0x7C0001B0,
+ "sllq.", 0x00000194, "=r,r,r;=Z", 0x00000001, 0x7C0001B1,
+ "slq", 0x00000195, "=r,r,r", 0x00000001, 0x7C000130,
+ "slq.", 0x00000195, "=r,r,r;=Z", 0x00000001, 0x7C000131,
+ "slw", 0x0000006A, "=r,r,r", 0x000FFFFF, 0x7C000030,
+ "slw.", 0x0000006A, "=r,r,r;=Z", 0x000FFFFF, 0x7C000031,
+ "sraiq", 0x00000196, "=r,r,u5", 0x00000001, 0x7C000770,
+ "sraiq.", 0x00000196, "=r,r,u5;=Z", 0x00000001, 0x7C000771,
+ "sraq", 0x00000197, "=r,r,r", 0x00000001, 0x7C000730,
+ "sraq.", 0x00000197, "=r,r,r;=Z", 0x00000001, 0x7C000731,
+ "sraw", 0x0000006D, "=r,r,r;+X", 0x000FFFFF, 0x7C000630,
+ "sraw.", 0x0000006D, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000631,
+ "srawi", 0x0000006C, "=r,r,u5;+X", 0x000FFFFF, 0x7C000670,
+ "srawi.", 0x0000006C, "=r,r,u5;+X=Z", 0x000FFFFF, 0x7C000671,
+ "sre", 0x00000198, "=r,r,r", 0x00000001, 0x7C000532,
+ "sre.", 0x00000198, "=r,r,r;=Z", 0x00000001, 0x7C000533,
+ "srea", 0x00000199, "=r,r,r", 0x00000001, 0x7C000732,
+ "srea.", 0x00000199, "=r,r,r;=Z", 0x00000001, 0x7C000733,
+ "sreq", 0x0000019A, "=r,r,r", 0x00000001, 0x7C0005B2,
+ "sreq.", 0x0000019A, "=r,r,r;=Z", 0x00000001, 0x7C0005B3,
+ "sriq", 0x0000019B, "=r,r,u5", 0x00000001, 0x7C000570,
+ "sriq.", 0x0000019B, "=r,r,u5;=Z", 0x00000001, 0x7C000571,
+ "srliq", 0x0000019C, "=r,r,u5", 0x00000001, 0x7C0005F0,
+ "srliq.", 0x0000019C, "=r,r,u5;=Z", 0x00000001, 0x7C0005F1,
+ "srlq", 0x0000019D, "=r,r,r", 0x00000001, 0x7C0005B0,
+ "srlq.", 0x0000019D, "=r,r,r;=Z", 0x00000001, 0x7C0005B1,
+ "srq", 0x0000019E, "=r,r,r", 0x00000001, 0x7C000530,
+ "srq.", 0x0000019E, "=r,r,r;=Z", 0x00000001, 0x7C000531,
+ "srw", 0x0000006B, "=r,r,r", 0x000FFFFF, 0x7C000430,
+ "srw.", 0x0000006B, "=r,r,r;=Z", 0x000FFFFF, 0x7C000431,
+ "stb", 0x00000028, "r,d(b)", 0x000FFFFF, 0x98000000,
+ "stbu", 0x00000029, "r,d(+b)", 0x000FFFFF, 0x9C000000,
+ "stbux", 0x0000002B, "r,(+b,r)", 0x000FFFFF, 0x7C0001EE,
+ "stbx", 0x0000002A, "r,(b,r)", 0x000FFFFF, 0x7C0001AE,
+ "stfd", 0x0000009A, "f,d(b)", 0x800FFFFF, 0xD8000000,
+ "stfdu", 0x0000009B, "f,d(+b)", 0x800FFFFF, 0xDC000000,
+ "stfdux", 0x0000009D, "f,(+b,r)", 0x800FFFFF, 0x7C0005EE,
+ "stfdx", 0x0000009C, "f,(b,r)", 0x800FFFFF, 0x7C0005AE,
+ "stfiwx", 0x000000BD, "f,(b,r)", 0x800FFFFE, 0x7C0007AE,
+ "stfs", 0x00000096, "f,d(b)", 0x800FFFFF, 0xD0000000,
+ "stfsu", 0x00000097, "f,d(+b)", 0x800FFFFF, 0xD4000000,
+ "stfsux", 0x00000099, "f,(+b,r)", 0x800FFFFF, 0x7C00056E,
+ "stfsx", 0x00000098, "f,(b,r)", 0x800FFFFF, 0x7C00052E,
+ "sth", 0x0000002C, "r,d(b)", 0x000FFFFF, 0xB0000000,
+ "sthbrx", 0x00000030, "r,(b,r)", 0x000FFFFF, 0x7C00072C,
+ "sthu", 0x0000002D, "r,d(+b)", 0x000FFFFF, 0xB4000000,
+ "sthux", 0x0000002F, "r,(+b,r)", 0x000FFFFF, 0x7C00036E,
+ "sthx", 0x0000002E, "r,(b,r)", 0x000FFFFF, 0x7C00032E,
+ "stmw", 0x00000036, "r,d(b)", 0x000FFFFF, 0xBC000000,
+ "stswi", 0x000000BE, "r,b,N", 0x000FFFFF, 0x7C0005AA,
+ "stswx", 0x000000BF, "r,(b,r)", 0x000FFFFF, 0x7C00052A,
+ "stw", 0x00000031, "r,d(b)", 0x000FFFFF, 0x90000000,
+ "stwbrx", 0x00000035, "r,(b,r)", 0x000FFFFF, 0x7C00052C,
+ "stwcx.", 0x000000C0, "r,(b,r);=Z", 0x000FFFFF, 0x7C00012D,
+ "stwu", 0x00000032, "r,d(+b)", 0x000FFFFF, 0x94000000,
+ "stwux", 0x00000034, "r,(+b,r)", 0x000FFFFF, 0x7C00016E,
+ "stwx", 0x00000033, "r,(b,r)", 0x000FFFFF, 0x7C00012E,
+ "subf", 0x0000004C, "=r,r,r", 0x000FFFFF, 0x7C000050,
+ "subf.", 0x0000004C, "=r,r,r;=Z", 0x000FFFFF, 0x7C000051,
+ "subfo", 0x0000004C, "=r,r,r;+X", 0x000FFFFF, 0x7C000450,
+ "subfo.", 0x0000004C, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000451,
+ "subfc", 0x0000004D, "=r,r,r;+X", 0x000FFFFF, 0x7C000010,
+ "subfc.", 0x0000004D, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000011,
+ "subfco", 0x0000004D, "=r,r,r;+X", 0x000FFFFF, 0x7C000410,
+ "subfco.", 0x0000004D, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000411,
+ "subfe", 0x0000004E, "=r,r,r;+X", 0x000FFFFF, 0x7C000110,
+ "subfe.", 0x0000004E, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000111,
+ "subfeo", 0x0000004E, "=r,r,r;+X", 0x000FFFFF, 0x7C000510,
+ "subfeo.", 0x0000004E, "=r,r,r;+X=Z", 0x000FFFFF, 0x7C000511,
+ "subfic", 0x0000004F, "=r,r,i;+X", 0x000FFFFF, 0x20000000,
+ "subfme", 0x00000050, "=r,r;+X", 0x000FFFFF, 0x7C0001D0,
+ "subfme.", 0x00000050, "=r,r;+X=Z", 0x000FFFFF, 0x7C0001D1,
+ "subfmeo", 0x00000050, "=r,r;+X", 0x000FFFFF, 0x7C0005D0,
+ "subfmeo.", 0x00000050, "=r,r;+X=Z", 0x000FFFFF, 0x7C0005D1,
+ "subfze", 0x00000051, "=r,r;+X", 0x000FFFFF, 0x7C000190,
+ "subfze.", 0x00000051, "=r,r;+X=Z", 0x000FFFFF, 0x7C000191,
+ "subfzeo", 0x00000051, "=r,r;+X", 0x000FFFFF, 0x7C000590,
+ "subfzeo.", 0x00000051, "=r,r;+X=Z", 0x000FFFFF, 0x7C000591,
+ "sync", 0x00000087, "", 0x000FFFFF, 0x7C0004AC,
+ "tlbia", 0x000000D2, "", 0x00000230, 0x7C0002E4,
+ "tlbie", 0x000000D3, "r", 0x040FFFFF, 0x7C000264,
+ "tlbld", 0x000000D4, "r", 0x00010006, 0x7C0007A4,
+ "tlbli", 0x000000D5, "r", 0x00010006, 0x7C0007E4,
+ "tlbsync", 0x000000D6, "", 0x040FFFFE, 0x7C00046C,
+ "tlbre", 0x000000E4, "=r,r,u1", 0x00000200, 0x7C000764,
+ "tlbrehi", 0x000000E4, "=r,r;%0", 0x00000200, 0x7C000764,
+ "tlbrelo", 0x000000E4, "=r,r;%1", 0x00000200, 0x7C000F64,
+ "tlbsx", 0x000000E5, "=r,(b,r)", 0x00000200, 0x7C000724,
+ "tlbsx.", 0x000000E5, "=r,(b,r);=Z", 0x00000200, 0x7C000725,
+ "tlbwe", 0x000000E6, "r,b,u1", 0x00000200, 0x7C0007A4,
+ "tlbwehi", 0x000000E6, "r,b;%0", 0x00000200, 0x7C0007A4,
+ "tlbwelo", 0x000000E6, "r,b;%1", 0x00000200, 0x7C000FA4,
+ "tw", 0x000000D7, "u5,r,r", 0x000FFFFF, 0x7C000008,
+ "twi", 0x000000D9, "u5,r,m", 0x000FFFFF, 0x0C000000,
+ "wrtee", 0x000000E7, "r", 0x000007C0, 0x7C000106,
+ "wrteei", 0x000000E8, "u1", 0x000007C0, 0x7C000146,
+ "xor", 0x0000005E, "=r,r,r", 0x000FFFFF, 0x7C000278,
+ "xor.", 0x0000005E, "=r,r,r;=Z", 0x000FFFFF, 0x7C000279,
+ "xori", 0x0000005A, "=r,r,x", 0x000FFFFF, 0x68000000,
+ "xoris", 0x0000005B, "=r,r,x", 0x000FFFFF, 0x6C000000,
+ "cmpw", 0x00000053, "=?c,r,r", 0x000FFFFF, 0x7C000000,
+ "cmpwi", 0x00000052, "=?c,r,i", 0x000FFFFF, 0x2C000000,
+ "cmplw", 0x00000055, "=?c,r,r", 0x000FFFFF, 0x7C000040,
+ "cmplwi", 0x00000054, "=?c,r,u", 0x000FFFFF, 0x28000000,
+ "la", 0x0000003F, "=r,d(b)", 0x000FFFFF, 0x38000000,
+ "las", 0x00000042, "=r,d(b)", 0x000FFFFF, 0x3C000000,
+ "li", 0x00000089, "=r,n", 0x000FFFFF, 0x38000000,
+ "lis", 0x0000008A, "=r,M", 0x000FFFFF, 0x3C000000,
+ "mr", 0x0000008B, "=r,r;p", 0x000FFFFF, 0x7C000378,
+ "mr.", 0x0000008B, "=r,r;p=Z", 0x000FFFFF, 0x7C000379,
+ "nop", 0x0000008C, "", 0x000FFFFF, 0x60000000,
+ "not", 0x0000008D, "=r,r", 0x000FFFFF, 0x7C0000F8,
+ "not.", 0x0000008D, "=r,r;=Z", 0x000FFFFF, 0x7C0000F9,
+ "sub", 0x0000004C, "=r,r,r/", 0x000FFFFF, 0x7C000050,
+ "sub.", 0x0000004C, "=r,r,r/;=Z", 0x000FFFFF, 0x7C000051,
+ "subo", 0x0000004C, "=r,r,r/;+X", 0x000FFFFF, 0x7C000450,
+ "subo.", 0x0000004C, "=r,r,r/;+X=Z", 0x000FFFFF, 0x7C000451,
+ "subc", 0x0000004D, "=r,r,r/;+X", 0x000FFFFF, 0x7C000010,
+ "subc.", 0x0000004D, "=r,r,r/;+X=Z", 0x000FFFFF, 0x7C000011,
+ "subco", 0x0000004D, "=r,r,r/;+X", 0x000FFFFF, 0x7C000410,
+ "subco.", 0x0000004D, "=r,r,r/;+X=Z", 0x000FFFFF, 0x7C000411,
+ "subi", 0x0000003F, "=r,b,-i;p", 0x000FFFFF, 0x38000000,
+ "subic", 0x00000040, "=r,r,-i;+X", 0x000FFFFF, 0x30000000,
+ "subic.", 0x00000041, "=r,r,-i;+X=Z", 0x000FFFFF, 0x34000000,
+ "subis", 0x00000042, "=r,b,-i", 0x000FFFFF, 0x3C000000,
+ "bctr", 0x00000012, ";Cpp", 0x000FFFFF, 0x4E800420,
+ "bctrl", 0x00000013, ";C=L", 0x000FFFFF, 0x4E800421,
+ "bdnzf", 0x0000000D, "Q,l;Cp", 0x000FFFFF, 0x40000000,
+ "bdnzfl", 0x0000000D, "Q,l;C=L", 0x000FFFFF, 0x40000001,
+ "bdnzfa", 0x0000000D, "Q,l;Cp", 0x000FFFFF, 0x40000002,
+ "bdnzfla", 0x0000000D, "Q,l;C=L", 0x000FFFFF, 0x40000003,
+ "bdnzflr", 0x00000003, "%0Q;CL", 0x000FFFFF, 0x4C000020,
+ "bdnzflrl", 0x00000003, "%0Q;C+L", 0x000FFFFF, 0x4C000021,
+ "bdnz", 0x0000000B, "l;Cp", 0x000FFFFF, 0x42000000,
+ "bdnzl", 0x0000000B, "l;C=L", 0x000FFFFF, 0x42000001,
+ "bdnza", 0x0000000B, "l;Cp", 0x000FFFFF, 0x42000002,
+ "bdnzla", 0x0000000B, "l;C=L", 0x000FFFFF, 0x42000003,
+ "bdnzlr", 0x00000003, ";%16%0%0CL", 0x000FFFFF, 0x4E000020,
+ "bdnzlrl", 0x00000003, ";%16%0%0C+L", 0x000FFFFF, 0x4E000021,
+ "bdnzt", 0x0000000C, "Q,l;Cp", 0x000FFFFF, 0x41000000,
+ "bdnztl", 0x0000000C, "Q,l;C=L", 0x000FFFFF, 0x41000001,
+ "bdnzta", 0x0000000C, "Q,l;Cp", 0x000FFFFF, 0x41000002,
+ "bdnztla", 0x0000000C, "Q,l;C=L", 0x000FFFFF, 0x41000003,
+ "bdnztlr", 0x00000003, "%8Q;CL", 0x000FFFFF, 0x4D000020,
+ "bdnztlrl", 0x00000003, "%8Q;C+L", 0x000FFFFF, 0x4D000021,
+ "bdzf", 0x00000010, "Q,l;Cp", 0x000FFFFF, 0x40400000,
+ "bdzfl", 0x00000010, "Q,l;C=L", 0x000FFFFF, 0x40400001,
+ "bdzfa", 0x00000010, "Q,l;Cp", 0x000FFFFF, 0x40400002,
+ "bdzfla", 0x00000010, "Q,l;C=L", 0x000FFFFF, 0x40400003,
+ "bdzflr", 0x00000003, "%2Q;CL", 0x000FFFFF, 0x4C400020,
+ "bdzflrl", 0x00000003, "%2Q;C+L", 0x000FFFFF, 0x4C400021,
+ "bdz", 0x0000000E, "l;Cp", 0x000FFFFF, 0x42400000,
+ "bdzl", 0x0000000E, "l;C=L", 0x000FFFFF, 0x42400001,
+ "bdza", 0x0000000E, "l;Cp", 0x000FFFFF, 0x42400002,
+ "bdzla", 0x0000000E, "l;C=L", 0x000FFFFF, 0x42400003,
+ "bdzlr", 0x00000003, ";%18%0%0CL", 0x000FFFFF, 0x4E400020,
+ "bdzlrl", 0x00000003, ";%18%0%0C+L", 0x000FFFFF, 0x4E400021,
+ "bdzt", 0x0000000F, "Q,l;Cp", 0x000FFFFF, 0x41400000,
+ "bdztl", 0x0000000F, "Q,l;C=L", 0x000FFFFF, 0x41400001,
+ "bdzta", 0x0000000F, "Q,l;Cp", 0x000FFFFF, 0x41400002,
+ "bdztla", 0x0000000F, "Q,l;C=L", 0x000FFFFF, 0x41400003,
+ "bdztlr", 0x00000003, "%10Q;CL", 0x000FFFFF, 0x4D400020,
+ "bdztlrl", 0x00000003, "%10Q;C+L", 0x000FFFFF, 0x4D400021,
+ "bf", 0x00000008, "Q,l;p", 0x000FFFFF, 0x40800000,
+ "bfl", 0x00000008, "Q,l;=L", 0x000FFFFF, 0x40800001,
+ "bfa", 0x00000008, "Q,l;p", 0x000FFFFF, 0x40800002,
+ "bfla", 0x00000008, "Q,l;=L", 0x000FFFFF, 0x40800003,
+ "bfctr", 0x0000000A, "Q;Cp", 0x000FFFFF, 0x4C800420,
+ "bfctrl", 0x0000000A, "Q;C=L", 0x000FFFFF, 0x4C800421,
+ "bflr", 0x00000009, "Q;L", 0x000FFFFF, 0x4C800020,
+ "bflrl", 0x00000009, "Q;+L", 0x000FFFFF, 0x4C800021,
+ "blr", 0x00000011, ";L", 0x000FFFFF, 0x4E800020,
+ "blrl", 0x00000014, ";+L", 0x000FFFFF, 0x4E800021,
+ "bt", 0x00000005, "Q,l;p", 0x000FFFFF, 0x41800000,
+ "btl", 0x00000005, "Q,l;=L", 0x000FFFFF, 0x41800001,
+ "bta", 0x00000005, "Q,l;p", 0x000FFFFF, 0x41800002,
+ "btla", 0x00000005, "Q,l;=L", 0x000FFFFF, 0x41800003,
+ "btctr", 0x00000007, "Q;Cp", 0x000FFFFF, 0x4D800420,
+ "btctrl", 0x00000007, "Q;C=L", 0x000FFFFF, 0x4D800421,
+ "btlr", 0x00000006, "Q;L", 0x000FFFFF, 0x4D800020,
+ "btlrl", 0x00000006, "Q;+L", 0x000FFFFF, 0x4D800021,
+ "beq", 0x00000005, "?c,%2l;p", 0x000FFFFF, 0x41820000,
+ "beql", 0x00000005, "?c,%2l;=L", 0x000FFFFF, 0x41820001,
+ "beqa", 0x00000005, "?c,%2l;p", 0x000FFFFF, 0x41820002,
+ "beqla", 0x00000005, "?c,%2l;=L", 0x000FFFFF, 0x41820003,
+ "beqctr", 0x00000007, "?c;%2Cp", 0x000FFFFF, 0x4D820420,
+ "beqctrl", 0x00000007, "?c;%2C=L", 0x000FFFFF, 0x4D820421,
+ "beqlr", 0x00000006, "?c;%2L", 0x000FFFFF, 0x4D820020,
+ "beqlrl", 0x00000006, "?c;%2+L", 0x000FFFFF, 0x4D820021,
+ "bge", 0x00000008, "?c,%0l;p", 0x000FFFFF, 0x40800000,
+ "bgel", 0x00000008, "?c,%0l;=L", 0x000FFFFF, 0x40800001,
+ "bgea", 0x00000008, "?c,%0l;p", 0x000FFFFF, 0x40800002,
+ "bgela", 0x00000008, "?c,%0l;=L", 0x000FFFFF, 0x40800003,
+ "bgectr", 0x0000000A, "?c;%0Cp", 0x000FFFFF, 0x4C800420,
+ "bgectrl", 0x0000000A, "?c;%0C=L", 0x000FFFFF, 0x4C800421,
+ "bgelr", 0x00000009, "?c;%0L", 0x000FFFFF, 0x4C800020,
+ "bgelrl", 0x00000009, "?c;%0+L", 0x000FFFFF, 0x4C800021,
+ "bgt", 0x00000005, "?c,%1l;p", 0x000FFFFF, 0x41810000,
+ "bgtl", 0x00000005, "?c,%1l;=L", 0x000FFFFF, 0x41810001,
+ "bgta", 0x00000005, "?c,%1l;p", 0x000FFFFF, 0x41810002,
+ "bgtla", 0x00000005, "?c,%1l;=L", 0x000FFFFF, 0x41810003,
+ "bgtctr", 0x00000007, "?c;%1Cp", 0x000FFFFF, 0x4D810420,
+ "bgtctrl", 0x00000007, "?c;%1C=L", 0x000FFFFF, 0x4D810421,
+ "bgtlr", 0x00000006, "?c;%1L", 0x000FFFFF, 0x4D810020,
+ "bgtlrl", 0x00000006, "?c;%1+L", 0x000FFFFF, 0x4D810021,
+ "ble", 0x00000008, "?c,%1l;p", 0x000FFFFF, 0x40810000,
+ "blel", 0x00000008, "?c,%1l;=L", 0x000FFFFF, 0x40810001,
+ "blea", 0x00000008, "?c,%1l;p", 0x000FFFFF, 0x40810002,
+ "blela", 0x00000008, "?c,%1l;=L", 0x000FFFFF, 0x40810003,
+ "blectr", 0x0000000A, "?c;%1Cp", 0x000FFFFF, 0x4C810420,
+ "blectrl", 0x0000000A, "?c;%1C=L", 0x000FFFFF, 0x4C810421,
+ "blelr", 0x00000009, "?c;%1L", 0x000FFFFF, 0x4C810020,
+ "blelrl", 0x00000009, "?c;%1+L", 0x000FFFFF, 0x4C810021,
+ "blt", 0x00000005, "?c,%0l;p", 0x000FFFFF, 0x41800000,
+ "bltl", 0x00000005, "?c,%0l;=L", 0x000FFFFF, 0x41800001,
+ "blta", 0x00000005, "?c,%0l;p", 0x000FFFFF, 0x41800002,
+ "bltla", 0x00000005, "?c,%0l;=L", 0x000FFFFF, 0x41800003,
+ "bltctr", 0x00000007, "?c;%0Cp", 0x000FFFFF, 0x4D800420,
+ "bltctrl", 0x00000007, "?c;%0C=L", 0x000FFFFF, 0x4D800421,
+ "bltlr", 0x00000006, "?c;%0L", 0x000FFFFF, 0x4D800020,
+ "bltlrl", 0x00000006, "?c;%0+L", 0x000FFFFF, 0x4D800021,
+ "bne", 0x00000008, "?c,%2l;p", 0x000FFFFF, 0x40820000,
+ "bnel", 0x00000008, "?c,%2l;=L", 0x000FFFFF, 0x40820001,
+ "bnea", 0x00000008, "?c,%2l;p", 0x000FFFFF, 0x40820002,
+ "bnela", 0x00000008, "?c,%2l;=L", 0x000FFFFF, 0x40820003,
+ "bnectr", 0x0000000A, "?c;%2Cp", 0x000FFFFF, 0x4C820420,
+ "bnectrl", 0x0000000A, "?c;%2C=L", 0x000FFFFF, 0x4C820421,
+ "bnelr", 0x00000009, "?c;%2L", 0x000FFFFF, 0x4C820020,
+ "bnelrl", 0x00000009, "?c;%2+L", 0x000FFFFF, 0x4C820021,
+ "bng", 0x00000008, "?c,%1l;p", 0x000FFFFF, 0x40810000,
+ "bngl", 0x00000008, "?c,%1l;=L", 0x000FFFFF, 0x40810001,
+ "bnga", 0x00000008, "?c,%1l;p", 0x000FFFFF, 0x40810002,
+ "bngla", 0x00000008, "?c,%1l;=L", 0x000FFFFF, 0x40810003,
+ "bngctr", 0x0000000A, "?c;%1Cp", 0x000FFFFF, 0x4C810420,
+ "bngctrl", 0x0000000A, "?c;%1C=L", 0x000FFFFF, 0x4C810421,
+ "bnglr", 0x00000009, "?c;%1L", 0x000FFFFF, 0x4C810020,
+ "bnglrl", 0x00000009, "?c;%1+L", 0x000FFFFF, 0x4C810021,
+ "bnl", 0x00000008, "?c,%0l;p", 0x000FFFFF, 0x40800000,
+ "bnll", 0x00000008, "?c,%0l;=L", 0x000FFFFF, 0x40800001,
+ "bnla", 0x00000008, "?c,%0l;p", 0x000FFFFF, 0x40800002,
+ "bnlla", 0x00000008, "?c,%0l;=L", 0x000FFFFF, 0x40800003,
+ "bnlctr", 0x0000000A, "?c;%0Cp", 0x000FFFFF, 0x4C800420,
+ "bnlctrl", 0x0000000A, "?c;%0C=L", 0x000FFFFF, 0x4C800421,
+ "bnllr", 0x00000009, "?c;%0L", 0x000FFFFF, 0x4C800020,
+ "bnllrl", 0x00000009, "?c;%0+L", 0x000FFFFF, 0x4C800021,
+ "bns", 0x00000008, "?c,%3l;p", 0x000FFFFF, 0x40830000,
+ "bnsl", 0x00000008, "?c,%3l;=L", 0x000FFFFF, 0x40830001,
+ "bnsa", 0x00000008, "?c,%3l;p", 0x000FFFFF, 0x40830002,
+ "bnsla", 0x00000008, "?c,%3l;=L", 0x000FFFFF, 0x40830003,
+ "bnsctr", 0x0000000A, "?c;%3Cp", 0x000FFFFF, 0x4C830420,
+ "bnsctrl", 0x0000000A, "?c;%3C=L", 0x000FFFFF, 0x4C830421,
+ "bnslr", 0x00000009, "?c;%3L", 0x000FFFFF, 0x4C830020,
+ "bnslrl", 0x00000009, "?c;%3+L", 0x000FFFFF, 0x4C830021,
+ "bnu", 0x00000008, "?c,%3l;p", 0x000FFFFF, 0x40830000,
+ "bnul", 0x00000008, "?c,%3l;=L", 0x000FFFFF, 0x40830001,
+ "bnua", 0x00000008, "?c,%3l;p", 0x000FFFFF, 0x40830002,
+ "bnula", 0x00000008, "?c,%3l;=L", 0x000FFFFF, 0x40830003,
+ "bnuctr", 0x0000000A, "?c;%3Cp", 0x000FFFFF, 0x4C830420,
+ "bnuctrl", 0x0000000A, "?c;%3C=L", 0x000FFFFF, 0x4C830421,
+ "bnulr", 0x00000009, "?c;%3L", 0x000FFFFF, 0x4C830020,
+ "bnulrl", 0x00000009, "?c;%3+L", 0x000FFFFF, 0x4C830021,
+ "bso", 0x00000005, "?c,%3l;p", 0x000FFFFF, 0x41830000,
+ "bsol", 0x00000005, "?c,%3l;=L", 0x000FFFFF, 0x41830001,
+ "bsoa", 0x00000005, "?c,%3l;p", 0x000FFFFF, 0x41830002,
+ "bsola", 0x00000005, "?c,%3l;=L", 0x000FFFFF, 0x41830003,
+ "bsoctr", 0x00000007, "?c;%3Cp", 0x000FFFFF, 0x4D830420,
+ "bsoctrl", 0x00000007, "?c;%3C=L", 0x000FFFFF, 0x4D830421,
+ "bsolr", 0x00000006, "?c;%3L", 0x000FFFFF, 0x4D830020,
+ "bsolrl", 0x00000006, "?c;%3+L", 0x000FFFFF, 0x4D830021,
+ "bun", 0x00000005, "?c,%3l;p", 0x000FFFFF, 0x41830000,
+ "bunl", 0x00000005, "?c,%3l;=L", 0x000FFFFF, 0x41830001,
+ "buna", 0x00000005, "?c,%3l;p", 0x000FFFFF, 0x41830002,
+ "bunla", 0x00000005, "?c,%3l;=L", 0x000FFFFF, 0x41830003,
+ "bunctr", 0x00000007, "?c;%3Cp", 0x000FFFFF, 0x4D830420,
+ "bunctrl", 0x00000007, "?c;%3C=L", 0x000FFFFF, 0x4D830421,
+ "bunlr", 0x00000006, "?c;%3L", 0x000FFFFF, 0x4D830020,
+ "bunlrl", 0x00000006, "?c;%3+L", 0x000FFFFF, 0x4D830021,
+ "mfxer", 0x0000007F, "=r;X", 0x000FFFFF, 0x7C0102A6,
+ "mflr", 0x00000081, "=r;L", 0x000FFFFF, 0x7C0802A6,
+ "mfctr", 0x00000080, "=r;C", 0x000FFFFF, 0x7C0902A6,
+ "mftb", 0x000000C7, "=r?T", 0x100FFFFF, 0x7C0C42E6,
+ "mftbu", 0x000000C7, "=r;S285", 0x100FFFFF, 0x7C0D42E6,
+ "mttbl", 0x0000007C, "=S284r", 0x100FFFFF, 0x7C1C43A6,
+ "mttbu", 0x0000007C, "=S285r", 0x100FFFFF, 0x7C1D43A6,
+ "mtxer", 0x00000077, "r;=X", 0x000FFFFF, 0x7C0103A6,
+ "mtctr", 0x00000078, "r;=C", 0x000FFFFF, 0x7C0903A6,
+ "mtlr", 0x00000079, "r;=L", 0x000FFFFF, 0x7C0803A6,
+ "mfdec", 0x0000007E, "=r;S22", 0x000FF83F, 0x7C1602A6,
+ "mfmq", 0x0000007E, "=r;S0", 0x00000001, 0x7C0002A6,
+ "mfrtcl", 0x0000007E, "=r;S5", 0x00000001, 0x7C0502A6,
+ "mfrtcu", 0x0000007E, "=r;S4", 0x00000001, 0x7C0402A6,
+ "mfdar", 0x0000007E, "=r;S19", 0x000FF83F, 0x7C1302A6,
+ "mfdbatl", 0x0000007E, "=r,P*2|537", 0x000FFFFF, 0x7C1982A6,
+ "mfdbatu", 0x0000007E, "=r,P*2|536", 0x000FFFFF, 0x7C1882A6,
+ "mfdsisr", 0x0000007E, "=r;S18", 0x000FF83F, 0x7C1202A6,
+ "mfear", 0x0000007E, "=r;S282", 0x000FFFCF, 0x7C1A42A6,
+ "mfibatl", 0x0000007E, "=r,P*2|529", 0x000FFFFF, 0x7C1182A6,
+ "mfibatu", 0x0000007E, "=r,P*2|528", 0x000FFFFF, 0x7C1082A6,
+ "mfpvr", 0x0000007E, "=r;S287", 0x000FFFFF, 0x7C1F42A6,
+ "mfsdr1", 0x0000007E, "=r;S25", 0x000FE00F, 0x7C1902A6,
+ "mfsprg", 0x0000007E, "=r,P|272", 0x000FFFFF, 0x7C1042A6,
+ "mfsrr0", 0x0000007E, "=r;S26", 0x000FFFFF, 0x7C1A02A6,
+ "mfsrr1", 0x0000007E, "=r;S27", 0x000FFFFF, 0x7C1B02A6,
+ "mtcr", 0x0000007A, "%255r;Y", 0x000FFFFF, 0x7C0FF120,
+ "mtfs", 0x00000084, "%255f", 0x800FFFFF, 0xFDFE058E,
+ "mtfs.", 0x00000084, "%255f;=Z", 0x800FFFFF, 0xFDFE058F,
+ "mtmq", 0x0000007C, "=S0r", 0x00000001, 0x7C0003A6,
+ "mtdar", 0x0000007C, "=S19r", 0x000FF83F, 0x7C1303A6,
+ "mtdbatl", 0x0000007C, "=P*2|537,r", 0x000FFFFF, 0x7C1983A6,
+ "mtdbatu", 0x0000007C, "=P*2|536,r", 0x000FFFFF, 0x7C1883A6,
+ "mtdec", 0x0000007C, "=S22r", 0x000FF83F, 0x7C1603A6,
+ "mtdsisr", 0x0000007C, "=S18r", 0x000FF83F, 0x7C1203A6,
+ "mtear", 0x0000007C, "=S282r", 0x000FFFCF, 0x7C1A43A6,
+ "mtibatl", 0x0000007C, "=P*2|529,r", 0x000FFFFF, 0x7C1183A6,
+ "mtibatu", 0x0000007C, "=P*2|528,r", 0x000FFFFF, 0x7C1083A6,
+ "mtsdr1", 0x0000007C, "=S25r", 0x000FE00F, 0x7C1903A6,
+ "mtsprg", 0x0000007C, "=P|272,r", 0x000FFFFF, 0x7C1043A6,
+ "mtsrr0", 0x0000007C, "=S26r", 0x000FFFFF, 0x7C1A03A6,
+ "mtsrr1", 0x0000007C, "=S27r", 0x000FFFFF, 0x7C1B03A6,
+ "mfcdbcr", 0x0000007E, "=r;S983", 0x000007C0, 0x7C17F2A6,
+ "mfdac1", 0x0000007E, "=r;S1014", 0x000007C0, 0x7C16FAA6,
+ "mfdac2", 0x0000007E, "=r;S1015", 0x00000080, 0x7C17FAA6,
+ "mfdbcr", 0x0000007E, "=r;S1010", 0x000007C0, 0x7C12FAA6,
+ "mfdbsr", 0x0000007E, "=r;S1008", 0x000007C0, 0x7C10FAA6,
+ "mfdccr", 0x0000007E, "=r;S1018", 0x000007C0, 0x7C1AFAA6,
+ "mfdcwr", 0x0000007E, "=r;S954", 0x00000240, 0x7C1AEAA6,
+ "mfdear", 0x0000007E, "=r;S981", 0x000007C0, 0x7C15F2A6,
+ "mfesr", 0x0000007E, "=r;S980", 0x000007C0, 0x7C14F2A6,
+ "mfevpr", 0x0000007E, "=r;S982", 0x000007C0, 0x7C16F2A6,
+ "mfiac1", 0x0000007E, "=r;S1012", 0x000007C0, 0x7C14FAA6,
+ "mfiac2", 0x0000007E, "=r;S1013", 0x00000080, 0x7C15FAA6,
+ "mficcr", 0x0000007E, "=r;S1019", 0x000007C0, 0x7C1BFAA6,
+ "mficdbdr", 0x0000007E, "=r;S979", 0x000007C0, 0x7C13F2A6,
+ "mfpid", 0x0000007E, "=r;S945", 0x00000200, 0x7C11EAA6,
+ "mfpit", 0x0000007E, "=r;S987", 0x000007C0, 0x7C1BF2A6,
+ "mfpbl1", 0x0000007E, "=r;S1020", 0x00000080, 0x7C1CFAA6,
+ "mfpbl2", 0x0000007E, "=r;S1022", 0x00000080, 0x7C1EFAA6,
+ "mfpbu1", 0x0000007E, "=r;S1021", 0x00000080, 0x7C1DFAA6,
+ "mfpbu2", 0x0000007E, "=r;S1023", 0x00000080, 0x7C1FFAA6,
+ "mfsgr", 0x0000007E, "=r;S953", 0x00000240, 0x7C19EAA6,
+ "mfsler", 0x0000007E, "=r;S955", 0x00000040, 0x7C1BEAA6,
+ "mfsprg0", 0x0000007E, "=r;S272", 0x000FFFFF, 0x7C1042A6,
+ "mfsprg1", 0x0000007E, "=r;S273", 0x000FFFFF, 0x7C1142A6,
+ "mfsprg2", 0x0000007E, "=r;S274", 0x000FFFFF, 0x7C1242A6,
+ "mfsprg3", 0x0000007E, "=r;S275", 0x000FFFFF, 0x7C1342A6,
+ "mfsrr2", 0x0000007E, "=r;S990", 0x000007C0, 0x7C1EF2A6,
+ "mfsrr3", 0x0000007E, "=r;S991", 0x000007C0, 0x7C1FF2A6,
+ "mftbhi", 0x0000007E, "=r;S988", 0x000007C0, 0x7C1CF2A6,
+ "mftbhu", 0x0000007E, "=r;S972", 0x00000240, 0x7C0CF2A6,
+ "mftblo", 0x0000007E, "=r;S989", 0x000007C0, 0x7C1DF2A6,
+ "mftblu", 0x0000007E, "=r;S973", 0x00000240, 0x7C0DF2A6,
+ "mftcr", 0x0000007E, "=r;S986", 0x000007C0, 0x7C1AF2A6,
+ "mftsr", 0x0000007E, "=r;S984", 0x000007C0, 0x7C18F2A6,
+ "mfzpr", 0x0000007E, "=r;S944", 0x00000200, 0x7C10EAA6,
+ "mtcdbcr", 0x0000007C, "=S983r", 0x000007C0, 0x7C17F3A6,
+ "mtdac1", 0x0000007C, "=S1014r", 0x000007C0, 0x7C16FBA6,
+ "mtdac2", 0x0000007C, "=S1015r", 0x00000080, 0x7C17FBA6,
+ "mtdbcr", 0x0000007C, "=S1010r", 0x000007C0, 0x7C12FBA6,
+ "mtdbsr", 0x0000007C, "=S1008r", 0x000007C0, 0x7C10FBA6,
+ "mtdccr", 0x0000007C, "=S1018r", 0x000007C0, 0x7C1AFBA6,
+ "mtdcwr", 0x0000007C, "=S954r", 0x00000240, 0x7C1AEBA6,
+ "mtdear", 0x0000007C, "=S981r", 0x000007C0, 0x7C15F3A6,
+ "mtesr", 0x0000007C, "=S980r", 0x000007C0, 0x7C14F3A6,
+ "mtevpr", 0x0000007C, "=S982r", 0x000007C0, 0x7C16F3A6,
+ "mtiac1", 0x0000007C, "=S1012r", 0x000007C0, 0x7C14FBA6,
+ "mtiac2", 0x0000007C, "=S1013r", 0x00000080, 0x7C15FBA6,
+ "mticcr", 0x0000007C, "=S1019r", 0x000007C0, 0x7C1BFBA6,
+ "mticdbdr", 0x0000007C, "=S979r", 0x000007C0, 0x7C13F3A6,
+ "mtpid", 0x0000007C, "=S945r", 0x00000200, 0x7C11EBA6,
+ "mtpit", 0x0000007C, "=S987r", 0x000007C0, 0x7C1BF3A6,
+ "mtpbl1", 0x0000007C, "=S1020r", 0x00000080, 0x7C1CFBA6,
+ "mtpbl2", 0x0000007C, "=S1022r", 0x00000080, 0x7C1EFBA6,
+ "mtpbu1", 0x0000007C, "=S1021r", 0x00000080, 0x7C1DFBA6,
+ "mtpbu2", 0x0000007C, "=S1023r", 0x00000080, 0x7C1FFBA6,
+ "mtsgr", 0x0000007C, "=S953r", 0x00000240, 0x7C19EBA6,
+ "mtsler", 0x0000007C, "=S955r", 0x00000040, 0x7C1BEBA6,
+ "mtsprg0", 0x0000007C, "=S272r", 0x000FFFFF, 0x7C1043A6,
+ "mtsprg1", 0x0000007C, "=S273r", 0x000FFFFF, 0x7C1143A6,
+ "mtsprg2", 0x0000007C, "=S274r", 0x000FFFFF, 0x7C1243A6,
+ "mtsprg3", 0x0000007C, "=S275r", 0x000FFFFF, 0x7C1343A6,
+ "mtsrr2", 0x0000007C, "=S990r", 0x000007C0, 0x7C1EF3A6,
+ "mtsrr3", 0x0000007C, "=S991r", 0x000007C0, 0x7C1FF3A6,
+ "mttbhi", 0x0000007C, "=S988r", 0x000007C0, 0x7C1CF3A6,
+ "mttblo", 0x0000007C, "=S989r", 0x000007C0, 0x7C1DF3A6,
+ "mttcr", 0x0000007C, "=S986r", 0x000007C0, 0x7C1AF3A6,
+ "mttsr", 0x0000007C, "=S984r", 0x000007C0, 0x7C18F3A6,
+ "mtzpr", 0x0000007C, "=S944r", 0x00000200, 0x7C10EBA6,
+ "mfbear", 0x000000E9, "=r;%144", 0x000007C0, 0x7C102286,
+ "mfbesr", 0x000000E9, "=r;%145", 0x00000080, 0x7C112286,
+ "mfbesr0", 0x000000E9, "=r;%145", 0x00000040, 0x7C112286,
+ "mfbr0", 0x000000E9, "=r;%128", 0x00000080, 0x7C002286,
+ "mfbrcr0", 0x000000E9, "=r;%128", 0x00000040, 0x7C002286,
+ "mfbr1", 0x000000E9, "=r;%129", 0x00000080, 0x7C012286,
+ "mfbrcr1", 0x000000E9, "=r;%129", 0x00000040, 0x7C012286,
+ "mfbr2", 0x000000E9, "=r;%130", 0x00000080, 0x7C022286,
+ "mfbrcr2", 0x000000E9, "=r;%130", 0x00000040, 0x7C022286,
+ "mfbr3", 0x000000E9, "=r;%131", 0x00000080, 0x7C032286,
+ "mfbrcr3", 0x000000E9, "=r;%131", 0x00000040, 0x7C032286,
+ "mfbr4", 0x000000E9, "=r;%132", 0x00000080, 0x7C042286,
+ "mfbrcr4", 0x000000E9, "=r;%132", 0x00000040, 0x7C042286,
+ "mfbr5", 0x000000E9, "=r;%133", 0x00000080, 0x7C052286,
+ "mfbrcr5", 0x000000E9, "=r;%133", 0x00000040, 0x7C052286,
+ "mfbr6", 0x000000E9, "=r;%134", 0x00000080, 0x7C062286,
+ "mfbrcr6", 0x000000E9, "=r;%134", 0x00000040, 0x7C062286,
+ "mfbr7", 0x000000E9, "=r;%135", 0x00000080, 0x7C072286,
+ "mfbrcr7", 0x000000E9, "=r;%135", 0x00000040, 0x7C072286,
+ "mfdmacc0", 0x000000E9, "=r;%196", 0x00000080, 0x7C043286,
+ "mfdmacc1", 0x000000E9, "=r;%204", 0x00000080, 0x7C0C3286,
+ "mfdmacc2", 0x000000E9, "=r;%212", 0x00000080, 0x7C143286,
+ "mfdmacc3", 0x000000E9, "=r;%220", 0x00000080, 0x7C1C3286,
+ "mfdmacr0", 0x000000E9, "=r;%192", 0x00000080, 0x7C003286,
+ "mfdmacr1", 0x000000E9, "=r;%200", 0x00000080, 0x7C083286,
+ "mfdmacr2", 0x000000E9, "=r;%208", 0x00000300, 0x7C103286,
+ "mfdmacr3", 0x000000E9, "=r;%216", 0x00000300, 0x7C183286,
+ "mfdmact0", 0x000000E9, "=r;%193", 0x00000080, 0x7C013286,
+ "mfdmact1", 0x000000E9, "=r;%201", 0x00000080, 0x7C093286,
+ "mfdmact2", 0x000000E9, "=r;%209", 0x00000300, 0x7C113286,
+ "mfdmact3", 0x000000E9, "=r;%217", 0x00000300, 0x7C193286,
+ "mfdmada0", 0x000000E9, "=r;%194", 0x00000080, 0x7C023286,
+ "mfdmada1", 0x000000E9, "=r;%202", 0x00000080, 0x7C0A3286,
+ "mfdmada2", 0x000000E9, "=r;%210", 0x00000300, 0x7C123286,
+ "mfdmada3", 0x000000E9, "=r;%218", 0x00000300, 0x7C1A3286,
+ "mfdmasa0", 0x000000E9, "=r;%195", 0x00000080, 0x7C033286,
+ "mfdmasa1", 0x000000E9, "=r;%203", 0x00000080, 0x7C0B3286,
+ "mfdmasa2", 0x000000E9, "=r;%211", 0x00000300, 0x7C133286,
+ "mfdmasa3", 0x000000E9, "=r;%219", 0x00000300, 0x7C1B3286,
+ "mfdmasr", 0x000000E9, "=r;%224", 0x00000080, 0x7C003A86,
+ "mfexisr", 0x000000E9, "=r;%64", 0x00000080, 0x7C001286,
+ "mfexier", 0x000000E9, "=r;%66", 0x00000080, 0x7C021286,
+ "mfiocr", 0x000000E9, "=r;%160", 0x000007C0, 0x7C002A86,
+ "mfpmcr0", 0x000000E9, "=r;%161", 0x00000040, 0x7C012A86,
+ "mtbear", 0x000000EA, "%144r", 0x000007C0, 0x7C102386,
+ "mtbesr", 0x000000EA, "%145r", 0x00000080, 0x7C112386,
+ "mtbesr0", 0x000000EA, "%145r", 0x00000080, 0x7C112386,
+ "mtbr0", 0x000000EA, "%128r", 0x00000080, 0x7C002386,
+ "mtbrcr0", 0x000000EA, "%128r", 0x00000040, 0x7C002386,
+ "mtbr1", 0x000000EA, "%129r", 0x00000080, 0x7C012386,
+ "mtbrcr1", 0x000000EA, "%129r", 0x00000040, 0x7C012386,
+ "mtbr2", 0x000000EA, "%130r", 0x00000080, 0x7C022386,
+ "mtbrcr2", 0x000000EA, "%130r", 0x00000040, 0x7C022386,
+ "mtbr3", 0x000000EA, "%131r", 0x00000080, 0x7C032386,
+ "mtbrcr3", 0x000000EA, "%131r", 0x00000040, 0x7C032386,
+ "mtbr4", 0x000000EA, "%132r", 0x00000080, 0x7C042386,
+ "mtbrcr4", 0x000000EA, "%132r", 0x00000040, 0x7C042386,
+ "mtbr5", 0x000000EA, "%133r", 0x00000080, 0x7C052386,
+ "mtbrcr5", 0x000000EA, "%133r", 0x00000040, 0x7C052386,
+ "mtbr6", 0x000000EA, "%134r", 0x00000080, 0x7C062386,
+ "mtbrcr6", 0x000000EA, "%134r", 0x00000040, 0x7C062386,
+ "mtbr7", 0x000000EA, "%135r", 0x00000080, 0x7C072386,
+ "mtbrcr7", 0x000000EA, "%135r", 0x00000040, 0x7C072386,
+ "mtdmacc0", 0x000000EA, "%196r", 0x00000080, 0x7C043386,
+ "mtdmacc1", 0x000000EA, "%204r", 0x00000080, 0x7C0C3386,
+ "mtdmacc2", 0x000000EA, "%212r", 0x00000300, 0x7C143386,
+ "mtdmacc3", 0x000000EA, "%220r", 0x00000300, 0x7C1C3386,
+ "mtdmacr0", 0x000000EA, "%192r", 0x00000080, 0x7C003386,
+ "mtdmacr1", 0x000000EA, "%200r", 0x00000080, 0x7C083386,
+ "mtdmacr2", 0x000000EA, "%208r", 0x00000300, 0x7C103386,
+ "mtdmacr3", 0x000000EA, "%216r", 0x00000300, 0x7C183386,
+ "mtdmact0", 0x000000EA, "%193r", 0x00000080, 0x7C013386,
+ "mtdmact1", 0x000000EA, "%201r", 0x00000080, 0x7C093386,
+ "mtdmact2", 0x000000EA, "%209r", 0x00000300, 0x7C113386,
+ "mtdmact3", 0x000000EA, "%217r", 0x00000300, 0x7C193386,
+ "mtdmada0", 0x000000EA, "%194r", 0x00000080, 0x7C023386,
+ "mtdmada1", 0x000000EA, "%202r", 0x00000080, 0x7C0A3386,
+ "mtdmada2", 0x000000EA, "%210r", 0x00000300, 0x7C123386,
+ "mtdmada3", 0x000000EA, "%218r", 0x00000300, 0x7C1A3386,
+ "mtdmasa0", 0x000000EA, "%195r", 0x00000080, 0x7C033386,
+ "mtdmasa1", 0x000000EA, "%203r", 0x00000080, 0x7C0B3386,
+ "mtdmasa2", 0x000000EA, "%211r", 0x00000300, 0x7C133386,
+ "mtdmasa3", 0x000000EA, "%219r", 0x00000300, 0x7C1B3386,
+ "mtdmasr", 0x000000EA, "%224r", 0x00000080, 0x7C003B86,
+ "mtexisr", 0x000000EA, "%64r", 0x00000080, 0x7C001386,
+ "mtexier", 0x000000EA, "%66r", 0x00000080, 0x7C021386,
+ "mtiocr", 0x000000EA, "%160r", 0x000007C0, 0x7C002B86,
+ "mtpmcr0", 0x000000EA, "%161r", 0x00000040, 0x7C012B86,
+ "trap", 0x000000D8, "", 0x000FFFFF, 0x7FE00008,
+ "tweq", 0x000000D7, "%4r,r", 0x000FFFFF, 0x7C800008,
+ "tweqi", 0x000000D9, "%4r,i", 0x000FFFFF, 0x0C800000,
+ "twge", 0x000000D7, "%12r,r", 0x000FFFFF, 0x7D800008,
+ "twgei", 0x000000D9, "%12r,i", 0x000FFFFF, 0x0D800000,
+ "twgt", 0x000000D7, "%8r,r", 0x000FFFFF, 0x7D000008,
+ "twgti", 0x000000D9, "%8r,i", 0x000FFFFF, 0x0D000000,
+ "twle", 0x000000D7, "%20r,r", 0x000FFFFF, 0x7E800008,
+ "twlei", 0x000000D9, "%20r,i", 0x000FFFFF, 0x0E800000,
+ "twlge", 0x000000D7, "%5r,r", 0x000FFFFF, 0x7CA00008,
+ "twlgei", 0x000000D9, "%5r,i", 0x000FFFFF, 0x0CA00000,
+ "twlgt", 0x000000D7, "%1r,r", 0x000FFFFF, 0x7C200008,
+ "twlgti", 0x000000D9, "%1r,i", 0x000FFFFF, 0x0C200000,
+ "twlle", 0x000000D7, "%6r,r", 0x000FFFFF, 0x7CC00008,
+ "twllei", 0x000000D9, "%6r,i", 0x000FFFFF, 0x0CC00000,
+ "twllt", 0x000000D7, "%2r,r", 0x000FFFFF, 0x7C400008,
+ "twllti", 0x000000D9, "%2r,i", 0x000FFFFF, 0x0C400000,
+ "twlng", 0x000000D7, "%6r,r", 0x000FFFFF, 0x7CC00008,
+ "twlngi", 0x000000D9, "%6r,i", 0x000FFFFF, 0x0CC00000,
+ "twlnl", 0x000000D7, "%5r,r", 0x000FFFFF, 0x7CA00008,
+ "twlnli", 0x000000D9, "%5r,i", 0x000FFFFF, 0x0CA00000,
+ "twlt", 0x000000D7, "%16r,r", 0x000FFFFF, 0x7E000008,
+ "twlti", 0x000000D9, "%16r,i", 0x000FFFFF, 0x0E000000,
+ "twne", 0x000000D7, "%24r,r", 0x000FFFFF, 0x7F000008,
+ "twnei", 0x000000D9, "%24r,i", 0x000FFFFF, 0x0F000000,
+ "twng", 0x000000D7, "%20r,r", 0x000FFFFF, 0x7E800008,
+ "twngi", 0x000000D9, "%20r,i", 0x000FFFFF, 0x0E800000,
+ "twnl", 0x000000D7, "%12r,r", 0x000FFFFF, 0x7D800008,
+ "twnli", 0x000000D9, "%12r,i", 0x000FFFFF, 0x0D800000,
+ "rotlwi", 0x00000067, "=r,r,u5;%0;%31", 0x000FFFFF, 0x5400003E,
+ "rotlwi.", 0x00000067, "=r,r,u5;%0;%31;=Z", 0x000FFFFF, 0x5400003F,
+ "rotrwi", 0x00000067, "=r,r,u5<31;%0;%31", 0x000FFFFF, 0x5400003E,
+ "rotrwi.", 0x00000067, "=r,r,u5<31;%0;%31;=Z", 0x000FFFFF, 0x5400003F,
+ "clrlslwi", 0x00000067, "=r,r,u5&,u5>p/<31", 0x000FFFFF, 0x54000000,
+ "clrlslwi.", 0x00000067, "=r,r,u5&,u5>p/<31;=Z", 0x000FFFFF, 0x54000001,
+ "clrlwi", 0x00000067, "=r,r,u5;%0/%31", 0x000FFFFF, 0x5400003E,
+ "clrlwi.", 0x00000067, "=r,r,u5;%0/%31=Z", 0x000FFFFF, 0x5400003F,
+ "clrrwi", 0x00000067, "=r,r,u5;%0;%0/2<31", 0x000FFFFF, 0x54000000,
+ "clrrwi.", 0x00000067, "=r,r,u5;%0;%0/2<31=Z", 0x000FFFFF, 0x54000001,
+ "extlwi", 0x00000067, "=r,r,u5,u5/>1%0/", 0x000FFFFF, 0x54000000,
+ "extlwi.", 0x00000067, "=r,r,u5,u5/>1%0/;=Z", 0x000FFFFF, 0x54000001,
+ "extrwi", 0x00000067, "=r,r,u5,u5|p/<32;%31", 0x000FFFFF, 0x5400003E,
+ "extrwi.", 0x00000067, "=r,r,u5,u5|p/<32;%31;=Z", 0x000FFFFF, 0x5400003F,
+ "slwi", 0x00000067, "=r,r,u5&<31%0/", 0x000FFFFF, 0x54000000,
+ "slwi.", 0x00000067, "=r,r,u5&<31%0/;=Z", 0x000FFFFF, 0x54000001,
+ "srwi", 0x00000067, "=r,r,u5&<32/%31", 0x000FFFFF, 0x5400003E,
+ "srwi.", 0x00000067, "=r,r,u5&<32/%31;=Z", 0x000FFFFF, 0x5400003F,
+ "rotlw", 0x00000068, "=r,r,r;%0%31", 0x000FFFFF, 0x5C00003E,
+ "rotlw.", 0x00000068, "=r,r,r;%0%31=Z", 0x000FFFFF, 0x5C00003F,
+ "inslwi", 0x00000069, "+r,r,u5,u5&<32/2|p>1", 0x000FFFFF, 0x50000000,
+ "inslwi.", 0x00000069, "+r,r,u5,u5&<32/2|p>1;=Z", 0x000FFFFF, 0x50000001,
+ "insrwi", 0x00000069, "+r,r,u5,u5/|p&<32/2/>1", 0x000FFFFF, 0x50000000,
+ "insrwi.", 0x00000069, "+r,r,u5,u5/|p&<32/2/>1;=Z", 0x000FFFFF, 0x50000001,
+ "crset", 0x00000070, "=Q&2&2", 0x000FFFFF, 0x4C000242,
+ "crnot", 0x00000072, "=Q,Q&2", 0x000FFFFF, 0x4C000042,
+ "crmove", 0x00000073, "=Q,Q&2", 0x000FFFFF, 0x4C000382,
+ "crclr", 0x00000075, "=Q&2&2", 0x000FFFFF, 0x4C000182,
+ "opword", 0x000000DA, "w", 0x000FFFFF, 0x00000000,
+ "dss", 0x000000EC, "u2?u2", 0x400FFFFF, 0x7C00066C,
+ "dssall", 0x000000ED, "", 0x400FFFFF, 0x7E00066C,
+ "dst", 0x000000EE, "r,r,u2?u2", 0x400FFFFF, 0x7C0002AC,
+ "dstt", 0x000000EF, "r,r,u2", 0x400FFFFF, 0x7E0002AC,
+ "dstst", 0x000000F0, "r,r,u2?u2", 0x400FFFFF, 0x7C0002EC,
+ "dststt", 0x000000F1, "r,r,u2", 0x400FFFFF, 0x7E0002EC,
+ "lvebx", 0x000000F2, "=v,(b,r)", 0x400FFFFF, 0x7C00000E,
+ "lvehx", 0x000000F3, "=v,(b,r)", 0x400FFFFF, 0x7C00004E,
+ "lvewx", 0x000000F4, "=v,(b,r)", 0x400FFFFF, 0x7C00008E,
+ "lvsl", 0x000000F5, "=v,(b,r)", 0x400FFFFF, 0x7C00000C,
+ "lvsr", 0x000000F6, "=v,(b,r)", 0x400FFFFF, 0x7C00004C,
+ "lvx", 0x000000F7, "=v,(b,r)", 0x400FFFFF, 0x7C0000CE,
+ "lvxl", 0x000000F8, "=v,(b,r)", 0x400FFFFF, 0x7C0002CE,
+ "mfvscr", 0x000000FE, "=v", 0x400FFFFF, 0x10000C08,
+ "mtvscr", 0x000000FF, "v", 0x400FFFFF, 0x10000C88,
+ "stvebx", 0x000000F9, "v,(b,r)", 0x400FFFFF, 0x7C00010E,
+ "stvehx", 0x000000FA, "v,(b,r)", 0x400FFFFF, 0x7C00014E,
+ "stvewx", 0x000000FB, "v,(b,r)", 0x400FFFFF, 0x7C00018E,
+ "stvx", 0x000000FC, "v,(b,r)", 0x400FFFFF, 0x7C0001CE,
+ "stvxl", 0x000000FD, "v,(b,r)", 0x400FFFFF, 0x7C0003CE,
+ "vaddcuw", 0x00000100, "=v,v,v", 0x400FFFFF, 0x10000180,
+ "vaddfp", 0x00000101, "=v,v,v", 0x400FFFFF, 0x1000000A,
+ "vaddsbs", 0x00000102, "=v,v,v", 0x400FFFFF, 0x10000300,
+ "vaddshs", 0x00000103, "=v,v,v", 0x400FFFFF, 0x10000340,
+ "vaddsws", 0x00000104, "=v,v,v", 0x400FFFFF, 0x10000380,
+ "vaddubm", 0x00000105, "=v,v,v", 0x400FFFFF, 0x10000000,
+ "vaddubs", 0x00000106, "=v,v,v", 0x400FFFFF, 0x10000200,
+ "vadduhm", 0x00000107, "=v,v,v", 0x400FFFFF, 0x10000040,
+ "vadduhs", 0x00000108, "=v,v,v", 0x400FFFFF, 0x10000240,
+ "vadduwm", 0x00000109, "=v,v,v", 0x400FFFFF, 0x10000080,
+ "vadduws", 0x0000010A, "=v,v,v", 0x400FFFFF, 0x10000280,
+ "vand", 0x0000010B, "=v,v,v", 0x400FFFFF, 0x10000404,
+ "vandc", 0x0000010C, "=v,v,v", 0x400FFFFF, 0x10000444,
+ "vavgsb", 0x0000010D, "=v,v,v", 0x400FFFFF, 0x10000502,
+ "vavgsh", 0x0000010E, "=v,v,v", 0x400FFFFF, 0x10000542,
+ "vavgsw", 0x0000010F, "=v,v,v", 0x400FFFFF, 0x10000582,
+ "vavgub", 0x00000110, "=v,v,v", 0x400FFFFF, 0x10000402,
+ "vavguh", 0x00000111, "=v,v,v", 0x400FFFFF, 0x10000442,
+ "vavguw", 0x00000112, "=v,v,v", 0x400FFFFF, 0x10000482,
+ "vcfsx", 0x00000113, "=v,v,u5", 0x400FFFFF, 0x1000034A,
+ "vcfux", 0x00000114, "=v,v,u5", 0x400FFFFF, 0x1000030A,
+ "vcmpbfp", 0x00000115, "=v,v,v", 0x400FFFFF, 0x100003C6,
+ "vcmpbfp.", 0x00000115, "=v,v,v;=Z", 0x400FFFFF, 0x100007C6,
+ "vcmpeqfp", 0x00000116, "=v,v,v", 0x400FFFFF, 0x100000C6,
+ "vcmpeqfp.", 0x00000116, "=v,v,v;=Z", 0x400FFFFF, 0x100004C6,
+ "vcmpequb", 0x00000117, "=v,v,v", 0x400FFFFF, 0x10000006,
+ "vcmpequb.", 0x00000117, "=v,v,v;=Z", 0x400FFFFF, 0x10000406,
+ "vcmpequh", 0x00000118, "=v,v,v", 0x400FFFFF, 0x10000046,
+ "vcmpequh.", 0x00000118, "=v,v,v;=Z", 0x400FFFFF, 0x10000446,
+ "vcmpequw", 0x00000119, "=v,v,v", 0x400FFFFF, 0x10000086,
+ "vcmpequw.", 0x00000119, "=v,v,v;=Z", 0x400FFFFF, 0x10000486,
+ "vcmpgefp", 0x0000011A, "=v,v,v", 0x400FFFFF, 0x100001C6,
+ "vcmpgefp.", 0x0000011A, "=v,v,v;=Z", 0x400FFFFF, 0x100005C6,
+ "vcmpgtfp", 0x0000011B, "=v,v,v", 0x400FFFFF, 0x100002C6,
+ "vcmpgtfp.", 0x0000011B, "=v,v,v;=Z", 0x400FFFFF, 0x100006C6,
+ "vcmpgtsb", 0x0000011C, "=v,v,v", 0x400FFFFF, 0x10000306,
+ "vcmpgtsb.", 0x0000011C, "=v,v,v;=Z", 0x400FFFFF, 0x10000706,
+ "vcmpgtsh", 0x0000011D, "=v,v,v", 0x400FFFFF, 0x10000346,
+ "vcmpgtsh.", 0x0000011D, "=v,v,v;=Z", 0x400FFFFF, 0x10000746,
+ "vcmpgtsw", 0x0000011E, "=v,v,v", 0x400FFFFF, 0x10000386,
+ "vcmpgtsw.", 0x0000011E, "=v,v,v;=Z", 0x400FFFFF, 0x10000786,
+ "vcmpgtub", 0x0000011F, "=v,v,v", 0x400FFFFF, 0x10000206,
+ "vcmpgtub.", 0x0000011F, "=v,v,v;=Z", 0x400FFFFF, 0x10000606,
+ "vcmpgtuh", 0x00000120, "=v,v,v", 0x400FFFFF, 0x10000246,
+ "vcmpgtuh.", 0x00000120, "=v,v,v;=Z", 0x400FFFFF, 0x10000646,
+ "vcmpgtuw", 0x00000121, "=v,v,v", 0x400FFFFF, 0x10000286,
+ "vcmpgtuw.", 0x00000121, "=v,v,v;=Z", 0x400FFFFF, 0x10000686,
+ "vctsxs", 0x00000122, "=v,v,u5", 0x400FFFFF, 0x100003CA,
+ "vctuxs", 0x00000123, "=v,v,u5", 0x400FFFFF, 0x1000038A,
+ "vexptefp", 0x00000124, "=v,v", 0x400FFFFF, 0x1000018A,
+ "vlogefp", 0x00000125, "=v,v", 0x400FFFFF, 0x100001CA,
+ "vmaxfp", 0x00000126, "=v,v,v", 0x400FFFFF, 0x1000040A,
+ "vmaxsb", 0x00000127, "=v,v,v", 0x400FFFFF, 0x10000102,
+ "vmaxsh", 0x00000128, "=v,v,v", 0x400FFFFF, 0x10000142,
+ "vmaxsw", 0x00000129, "=v,v,v", 0x400FFFFF, 0x10000182,
+ "vmaxub", 0x0000012A, "=v,v,v", 0x400FFFFF, 0x10000002,
+ "vmaxuh", 0x0000012B, "=v,v,v", 0x400FFFFF, 0x10000042,
+ "vmaxuw", 0x0000012C, "=v,v,v", 0x400FFFFF, 0x10000082,
+ "vminfp", 0x0000012D, "=v,v,v", 0x400FFFFF, 0x1000044A,
+ "vminsb", 0x0000012E, "=v,v,v", 0x400FFFFF, 0x10000302,
+ "vminsh", 0x0000012F, "=v,v,v", 0x400FFFFF, 0x10000342,
+ "vminsw", 0x00000130, "=v,v,v", 0x400FFFFF, 0x10000382,
+ "vminub", 0x00000131, "=v,v,v", 0x400FFFFF, 0x10000202,
+ "vminuh", 0x00000132, "=v,v,v", 0x400FFFFF, 0x10000242,
+ "vminuw", 0x00000133, "=v,v,v", 0x400FFFFF, 0x10000282,
+ "vmrghb", 0x00000134, "=v,v,v", 0x400FFFFF, 0x1000000C,
+ "vmrghh", 0x00000135, "=v,v,v", 0x400FFFFF, 0x1000004C,
+ "vmrghw", 0x00000136, "=v,v,v", 0x400FFFFF, 0x1000008C,
+ "vmrglb", 0x00000137, "=v,v,v", 0x400FFFFF, 0x1000010C,
+ "vmrglh", 0x00000138, "=v,v,v", 0x400FFFFF, 0x1000014C,
+ "vmrglw", 0x00000139, "=v,v,v", 0x400FFFFF, 0x1000018C,
+ "vmulesb", 0x0000013A, "=v,v,v", 0x400FFFFF, 0x10000308,
+ "vmulesh", 0x0000013B, "=v,v,v", 0x400FFFFF, 0x10000348,
+ "vmuleub", 0x0000013C, "=v,v,v", 0x400FFFFF, 0x10000208,
+ "vmuleuh", 0x0000013D, "=v,v,v", 0x400FFFFF, 0x10000248,
+ "vmulosb", 0x0000013E, "=v,v,v", 0x400FFFFF, 0x10000108,
+ "vmulosh", 0x0000013F, "=v,v,v", 0x400FFFFF, 0x10000148,
+ "vmuloub", 0x00000140, "=v,v,v", 0x400FFFFF, 0x10000008,
+ "vmulouh", 0x00000141, "=v,v,v", 0x400FFFFF, 0x10000048,
+ "vnor", 0x00000142, "=v,v,v", 0x400FFFFF, 0x10000504,
+ "vnot", 0x00000142, "=v,v&", 0x400FFFFF, 0x10000504,
+ "vor", 0x00000143, "=v,v,v", 0x400FFFFF, 0x10000484,
+ "vpkpx", 0x00000144, "=v,v,v", 0x400FFFFF, 0x1000030E,
+ "vpkshss", 0x00000145, "=v,v,v", 0x400FFFFF, 0x1000018E,
+ "vpkshus", 0x00000146, "=v,v,v", 0x400FFFFF, 0x1000010E,
+ "vpkswss", 0x00000147, "=v,v,v", 0x400FFFFF, 0x100001CE,
+ "vpkswus", 0x00000148, "=v,v,v", 0x400FFFFF, 0x1000014E,
+ "vpkuhum", 0x00000149, "=v,v,v", 0x400FFFFF, 0x1000000E,
+ "vpkuhus", 0x0000014A, "=v,v,v", 0x400FFFFF, 0x1000008E,
+ "vpkuwum", 0x0000014B, "=v,v,v", 0x400FFFFF, 0x1000004E,
+ "vpkuwus", 0x0000014C, "=v,v,v", 0x400FFFFF, 0x100000CE,
+ "vrefp", 0x0000014D, "=v,v", 0x400FFFFF, 0x1000010A,
+ "vrfim", 0x0000014E, "=v,v", 0x400FFFFF, 0x100002CA,
+ "vrfin", 0x0000014F, "=v,v", 0x400FFFFF, 0x1000020A,
+ "vrfip", 0x00000150, "=v,v", 0x400FFFFF, 0x1000028A,
+ "vrfiz", 0x00000151, "=v,v", 0x400FFFFF, 0x1000024A,
+ "vrlb", 0x00000152, "=v,v,v", 0x400FFFFF, 0x10000004,
+ "vrlh", 0x00000153, "=v,v,v", 0x400FFFFF, 0x10000044,
+ "vrlw", 0x00000154, "=v,v,v", 0x400FFFFF, 0x10000084,
+ "vrsqrtefp", 0x00000155, "=v,v", 0x400FFFFF, 0x1000014A,
+ "vsl", 0x00000156, "=v,v,v", 0x400FFFFF, 0x100001C4,
+ "vslb", 0x00000157, "=v,v,v", 0x400FFFFF, 0x10000104,
+ "vslh", 0x00000158, "=v,v,v", 0x400FFFFF, 0x10000144,
+ "vslo", 0x00000159, "=v,v,v", 0x400FFFFF, 0x1000040C,
+ "vslw", 0x0000015A, "=v,v,v", 0x400FFFFF, 0x10000184,
+ "vspltb", 0x0000015B, "=v,v,u5", 0x400FFFFF, 0x1000020C,
+ "vsplth", 0x0000015C, "=v,v,u5", 0x400FFFFF, 0x1000024C,
+ "vspltw", 0x0000015D, "=v,v,u5", 0x400FFFFF, 0x1000028C,
+ "vspltisb", 0x0000015E, "=v,i5", 0x400FFFFF, 0x1000030C,
+ "vspltish", 0x0000015F, "=v,i5", 0x400FFFFF, 0x1000034C,
+ "vspltisw", 0x00000160, "=v,i5", 0x400FFFFF, 0x1000038C,
+ "vsr", 0x00000161, "=v,v,v", 0x400FFFFF, 0x100002C4,
+ "vsrab", 0x00000162, "=v,v,v", 0x400FFFFF, 0x10000304,
+ "vsrah", 0x00000163, "=v,v,v", 0x400FFFFF, 0x10000344,
+ "vsraw", 0x00000164, "=v,v,v", 0x400FFFFF, 0x10000384,
+ "vsrb", 0x00000165, "=v,v,v", 0x400FFFFF, 0x10000204,
+ "vsrh", 0x00000166, "=v,v,v", 0x400FFFFF, 0x10000244,
+ "vsro", 0x00000167, "=v,v,v", 0x400FFFFF, 0x1000044C,
+ "vsrw", 0x00000168, "=v,v,v", 0x400FFFFF, 0x10000284,
+ "vsubcuw", 0x00000169, "=v,v,v", 0x400FFFFF, 0x10000580,
+ "vsubfp", 0x0000016A, "=v,v,v", 0x400FFFFF, 0x1000004A,
+ "vsubsbs", 0x0000016B, "=v,v,v", 0x400FFFFF, 0x10000700,
+ "vsubshs", 0x0000016C, "=v,v,v", 0x400FFFFF, 0x10000740,
+ "vsubsws", 0x0000016D, "=v,v,v", 0x400FFFFF, 0x10000780,
+ "vsububm", 0x0000016E, "=v,v,v", 0x400FFFFF, 0x10000400,
+ "vsububs", 0x0000016F, "=v,v,v", 0x400FFFFF, 0x10000600,
+ "vsubuhm", 0x00000170, "=v,v,v", 0x400FFFFF, 0x10000440,
+ "vsubuhs", 0x00000171, "=v,v,v", 0x400FFFFF, 0x10000640,
+ "vsubuwm", 0x00000172, "=v,v,v", 0x400FFFFF, 0x10000480,
+ "vsubuws", 0x00000173, "=v,v,v", 0x400FFFFF, 0x10000680,
+ "vsumsws", 0x00000174, "=v,v,v", 0x400FFFFF, 0x10000788,
+ "vsum2sws", 0x00000175, "=v,v,v", 0x400FFFFF, 0x10000688,
+ "vsum4sbs", 0x00000176, "=v,v,v", 0x400FFFFF, 0x10000708,
+ "vsum4shs", 0x00000177, "=v,v,v", 0x400FFFFF, 0x10000648,
+ "vsum4ubs", 0x00000178, "=v,v,v", 0x400FFFFF, 0x10000608,
+ "vupkhpx", 0x00000179, "=v,v", 0x400FFFFF, 0x1000034E,
+ "vupkhsb", 0x0000017A, "=v,v", 0x400FFFFF, 0x1000020E,
+ "vupkhsh", 0x0000017B, "=v,v", 0x400FFFFF, 0x1000024E,
+ "vupklpx", 0x0000017C, "=v,v", 0x400FFFFF, 0x100003CE,
+ "vupklsb", 0x0000017D, "=v,v", 0x400FFFFF, 0x1000028E,
+ "vupklsh", 0x0000017E, "=v,v", 0x400FFFFF, 0x100002CE,
+ "vxor", 0x0000017F, "=v,v,v", 0x400FFFFF, 0x100004C4,
+ "vmaddfp", 0x00000180, "=v,v,v,v", 0x400FFFFF, 0x1000002E,
+ "vmhaddshs", 0x00000181, "=v,v,v,v", 0x400FFFFF, 0x10000020,
+ "vmhraddshs", 0x00000182, "=v,v,v,v", 0x400FFFFF, 0x10000021,
+ "vmladduhm", 0x00000183, "=v,v,v,v", 0x400FFFFF, 0x10000022,
+ "vmsummbm", 0x00000184, "=v,v,v,v", 0x400FFFFF, 0x10000025,
+ "vmsumshm", 0x00000185, "=v,v,v,v", 0x400FFFFF, 0x10000028,
+ "vmsumshs", 0x00000186, "=v,v,v,v", 0x400FFFFF, 0x10000029,
+ "vmsumubm", 0x00000187, "=v,v,v,v", 0x400FFFFF, 0x10000024,
+ "vmsumuhm", 0x00000188, "=v,v,v,v", 0x400FFFFF, 0x10000026,
+ "vmsumuhs", 0x00000189, "=v,v,v,v", 0x400FFFFF, 0x10000027,
+ "vnmsubfp", 0x0000018A, "=v,v,v,v", 0x400FFFFF, 0x1000002F,
+ "vperm", 0x0000018B, "=v,v,v,v", 0x400FFFFF, 0x1000002B,
+ "vsel", 0x0000018C, "=v,v,v,v", 0x400FFFFF, 0x1000002A,
+ "vsldoi", 0x0000018D, "=v,v,v,u4", 0x400FFFFF, 0x1000002C,
+ "vmr", 0x0000018E, "=v,v", 0x400FFFFF, 0x10000484,
+ "vmrp", 0x0000018F, "=v,v", 0x400FFFFF, 0x1000002C,
+ "mtvrsave", 0x0000007C, "=S256r", 0x400FFFFF, 0x7C0043A6,
+ "mfvrsave", 0x0000007E, "=r;S256", 0x400FFFFF, 0x7C0042A6,
+ NULL, 0, NULL, 0, 0
+};
+
+typedef struct HashedMnemonic {
+ struct HashedMnemonic *next;
+ IAMnemonic *mnemonic;
+} HashedMnemonic;
+
+HashedMnemonic *hashedmnemonics[1024];
+
+void InlineAsm_InitializeMnemonicsPPC(void) {
+ SInt32 i;
+ IAMnemonic *mnemonic;
+ HashedMnemonic **ptr;
+ HashedMnemonic *entry;
+
+ for (i = 0; i < 1024; i++)
+ hashedmnemonics[i] = NULL;
+
+ for (mnemonic = mnemonics; mnemonic->name; mnemonic++) {
+ ptr = hashedmnemonics + (CHash(mnemonic->name) & 1023);
+ entry = lalloc(sizeof(HashedMnemonic));
+ entry->mnemonic = mnemonic;
+ entry->next = *ptr;
+ *ptr = entry;
+ }
+}
+
+IAMnemonic *InlineAsm_LookupMnemonicPPC(char *name) {
+ HashedMnemonic *entry;
+
+ for (entry = hashedmnemonics[CHash(name) & 1023]; entry; entry = entry->next) {
+ IAMnemonic *mnemonic = entry->mnemonic;
+ if (!strcmp(mnemonic->name, name))
+ return mnemonic;
+ }
+
+ return NULL;
+}
diff --git a/compiler_and_linker/unsorted/InlineAsmPPC.c b/compiler_and_linker/unsorted/InlineAsmPPC.c
new file mode 100644
index 0000000..ead84d7
--- /dev/null
+++ b/compiler_and_linker/unsorted/InlineAsmPPC.c
@@ -0,0 +1,2624 @@
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/CError.h"
+#include "compiler/CInt64.h"
+#include "compiler/CFunc.h"
+#include "compiler/CMachine.h"
+#include "compiler/CParser.h"
+#include "compiler/CPrep.h"
+#include "compiler/CPrepTokenizer.h"
+#include "compiler/TOC.h"
+#include "compiler/FuncLevelAsmPPC.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmMnemonicsPPC.h"
+#include "compiler/InlineAsmRegisters.h"
+#include "compiler/InlineAsmRegistersPPC.h"
+#include "compiler/CodeGen.h"
+#include "compiler/CodeGenOptPPC.h"
+#include "compiler/PPCError.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/objects.h"
+#include "compiler/CExpr.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/StackFrame.h"
+#include "compiler/CompilerTools.h"
+
+// TODO: move me
+extern int countexceptionactionregisters(ExceptionAction *);
+extern void noteexceptionactionregisters(ExceptionAction *, PCodeArg *);
+extern void *make_alias(Object *obj, SInt32 offset, SInt32 size);
+
+char asm_alloc_flags[10];
+unsigned char sm_section;
+UInt32 cpu;
+SInt32 fralloc_parameter_area_size;
+Boolean user_responsible_for_frame;
+Boolean supports_hardware_fpu;
+UInt32 assembledinstructions;
+UInt8 assembler_type;
+char volatileasm;
+Boolean InlineAsm_gccmode;
+Boolean InlineAsm_labelref;
+CLabel *pic_base_label;
+
+enum {
+ NO_REG = 0,
+ INVALID_PIC_REG = -2
+};
+
+// forward decls
+static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value);
+static Object *isvariableoperand(void);
+static Object *isregisterstructpointeroperand(void);
+static void registeroperand(IAOperand *op, char rclass, short effect);
+static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right);
+static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value);
+static void savepicbase(short reg, HashNameNode *name);
+
+inline SInt32 ExtractValue(CInt64 value) {
+ return (SInt32) CInt64_GetULong(&value);
+}
+
+static void IllegalObjectOperator(HashNameNode *name1, HashNameNode *name2, short token) {
+ char *opstr;
+ switch (token) {
+ case '*': opstr = "*"; break;
+ case '/': opstr = "/"; break;
+ case '%': opstr = "%"; break;
+ case '+': opstr = "+"; break;
+ case '-': opstr = "-"; break;
+ case TK_SHL: opstr = "<<"; break;
+ case TK_SHR: opstr = ">>"; break;
+ case '<': opstr = "<"; break;
+ case '>': opstr = ">"; break;
+ case TK_LESS_EQUAL: opstr = "<="; break;
+ case TK_GREATER_EQUAL: opstr = ">="; break;
+ case TK_LOGICAL_EQ: opstr = "=="; break;
+ case TK_LOGICAL_NE: opstr = "!="; break;
+ case '&': opstr = "&"; break;
+ case '^': opstr = "^"; break;
+ case '|': opstr = "|"; break;
+ case TK_LOGICAL_AND: opstr = "&&"; break;
+ case TK_LOGICAL_OR: opstr = "||"; break;
+ default: opstr = "???";
+ }
+
+ if (!name2) {
+ PPCError_Error(119, opstr, name1->name);
+ } else if (!name1) {
+ PPCError_Error(120, opstr, name2->name);
+ } else {
+ PPCError_Error(118, name1->name, opstr, name2->name);
+ }
+}
+
+static void IllegalObjectInConst(IAExpr *expr) {
+ if (expr->xC) {
+ PPCError_Error(122, expr->xC->name->name);
+ } else if (expr->object) {
+ PPCError_Error(122, expr->object->name->name);
+ } else if (expr->label) {
+ PPCError_Error(166, expr->label->name->name);
+ }
+}
+
+static void NotInRegisterError(char *name, char rclass) {
+ PPCError_Error(167, name, register_class_name[rclass]);
+}
+
+static int isregisteroperand(char rclass) {
+ IARegister *reg;
+
+ return (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass);
+}
+
+static SInt32 getcroperand(char rclass) {
+ SInt32 value;
+ IARegister *reg;
+
+ value = 0;
+ if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) {
+ value = reg->num;
+ } else {
+ PPCError_Error(167, tkidentifier->name);
+ }
+
+ tk = lex();
+ return value;
+}
+
+static SInt32 getimmediateoperand(SInt32 minimum, SInt32 maximum) {
+ SInt32 value = InlineAsm_ConstantExpressionPPC(0);
+ if (value < minimum || value > maximum)
+ CError_Error(CErrorStr154);
+ return value;
+}
+
+static void PrimaryExpressionPPC(IAExpr *expr, SInt32 value) {
+ Object *obj;
+ IALookupResult result;
+ IAExpr subexpr;
+ IAExprType type = IAExpr_0;
+ SInt32 v;
+
+ switch (tk) {
+ case TK_IDENTIFIER:
+ if ((obj = isregisterstructpointeroperand())) {
+ tk = lex();
+ InlineAsm_InitExpr5(expr, InlineAsm_StructPointerMemberOffset(TPTR_TARGET(obj->type)));
+ expr->object = obj;
+ return;
+ }
+
+ if ((obj = isvariableoperand())) {
+ short reg;
+ InlineAsm_InitExpr5(expr, 0);
+ expr->xC = obj;
+
+ if (obj->datatype == DLOCAL)
+ reg = 1;
+ else
+ reg = pic_base_reg;
+
+ tk = lex();
+ if (tk == '.' || tk == '[') {
+ InlineAsm_InitExpr5(&subexpr, InlineAsm_StructArrayMemberOffset(obj->type));
+ DiadicOperatorPPC(expr, '+', &subexpr);
+ }
+
+ if (tk == '+') {
+ tk = lex();
+ InlineAsm_ExpressionPPC(&subexpr, value);
+ DiadicOperatorPPC(expr, '+', &subexpr);
+ } else if (tk == '-') {
+ tk = lex();
+ InlineAsm_ExpressionPPC(&subexpr, value);
+ DiadicOperatorPPC(expr, '-', &subexpr);
+ } else if (!strcmp(tkidentifier->name, "@loword")) {
+ tk = lex();
+ if (low_offset) {
+ InlineAsm_InitExpr5(&subexpr, low_offset);
+ DiadicOperatorPPC(expr, '+', &subexpr);
+ }
+ } else if (!strcmp(tkidentifier->name, "@hiword")) {
+ tk = lex();
+ if (high_offset) {
+ InlineAsm_InitExpr5(&subexpr, high_offset);
+ DiadicOperatorPPC(expr, '+', &subexpr);
+ }
+ }
+ expr->reg = reg;
+ return;
+ }
+
+ if (InlineAsm_LookupSymbolOrTag(tkidentifier, &result, 1)) {
+ if (result.has_value) {
+ tk = lex();
+ InlineAsm_InitExpr5(expr, result.value);
+ return;
+ }
+
+ if (result.type && (IS_TYPE_STRUCT(result.type) || IS_TYPE_CLASS(result.type))) {
+ tk = lex();
+ if (tk != '.')
+ CError_Error(CErrorStr120);
+
+ if (allow_array_expressions) {
+ InlineAsm_InitExpr5(expr, InlineAsm_StructArrayMemberOffset(result.type));
+ return;
+ }
+
+ InlineAsm_InitExpr5(expr, InlineAsm_StructMemberOffset(result.type));
+ return;
+ }
+
+ if (result.object && result.object->datatype == DABSOLUTE) {
+ tk = lex();
+ InlineAsm_InitExpr5(expr, result.object->u.address);
+ return;
+ }
+ } else if (value) {
+ if (isregisteroperand(RegClass_CRFIELD)) {
+ InlineAsm_InitExpr5(expr, getcroperand(RegClass_CRFIELD));
+ return;
+ }
+ if (isregisteroperand(RegClass_6)) {
+ InlineAsm_InitExpr5(expr, getcroperand(RegClass_6));
+ return;
+ }
+ if (strlen(tkidentifier->name) == 6 && !strncmp(tkidentifier->name, "cr", 2) && tkidentifier->name[3] == '_') {
+ IARegister *reg;
+ char regname[4];
+ regname[0] = tkidentifier->name[0];
+ regname[1] = tkidentifier->name[1];
+ regname[2] = tkidentifier->name[2];
+ regname[3] = 0;
+ if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_CRFIELD) {
+ SInt32 v = reg->num * 4;
+ regname[0] = tkidentifier->name[4];
+ regname[1] = tkidentifier->name[5];
+ regname[2] = 0;
+ if ((reg = InlineAsm_LookupRegisterPPC(regname)) && reg->rclass == RegClass_6) {
+ tk = lex();
+ InlineAsm_InitExpr5(expr, v + reg->num);
+ return;
+ }
+ }
+ }
+ }
+
+ if (!strcmp("ha16", tkidentifier->name))
+ type = IAExpr_8;
+ else if (!strcmp("hi16", tkidentifier->name))
+ type = IAExpr_7;
+ else if (!strcmp("lo16", tkidentifier->name))
+ type = IAExpr_6;
+
+ if (type != IAExpr_0) {
+ tk = lex();
+ if (tk == '(') {
+ SInt32 v;
+ tk = lex();
+ PrimaryExpressionPPC(expr, value);
+ expr->type = type;
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+
+ tk = lex();
+ if (InlineAsm_CheckExpr(expr)) {
+ expr->value = InlineAsm_GetExprValue(expr);
+ expr->type = IAExpr_5;
+ }
+ return;
+ }
+
+ CError_Error(CErrorStr114);
+ } else {
+ if (!result.label)
+ result.label = InlineAsm_DeclareLabel(tkidentifier);
+
+ InlineAsm_InitExpr5(expr, 0);
+ expr->flags |= IAFlag1;
+ expr->label = result.label;
+ tk = lex();
+ return;
+ }
+ break;
+
+ case TK_INTCONST:
+ v = CInt64_GetULong(&tkintconst);
+ tk = lex();
+ InlineAsm_InitExpr5(expr, v);
+ return;
+
+ case TK_SIZEOF:
+ InlineAsm_InitExpr5(expr, scansizeof());
+ return;
+
+ case '+':
+ tk = lex();
+ PrimaryExpressionPPC(expr, value);
+ return;
+
+ case '-':
+ tk = lex();
+ PrimaryExpressionPPC(expr, value);
+ if (InlineAsm_CheckExpr(expr))
+ expr->value = -expr->value;
+ else
+ CError_Error(CErrorStr124);
+ return;
+
+ case '!':
+ tk = lex();
+ PrimaryExpressionPPC(expr, value);
+ if (InlineAsm_CheckExpr(expr))
+ expr->value = !expr->value;
+ else
+ CError_Error(CErrorStr124);
+ return;
+
+ case '~':
+ tk = lex();
+ PrimaryExpressionPPC(expr, value);
+ if (InlineAsm_CheckExpr(expr))
+ expr->value = ~expr->value;
+ else
+ CError_Error(CErrorStr124);
+ return;
+
+ case '(':
+ tk = lex();
+ InlineAsm_ExpressionPPC(expr, value);
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ tk = lex();
+ return;
+
+ default:
+ CError_Error(CErrorStr120);
+ }
+
+ InlineAsm_InitExpr5(expr, 0);
+}
+
+static void DiadicOperatorPPC(IAExpr *left, short token, IAExpr *right) {
+ CInt64 leftval;
+ CInt64 rightval;
+
+ CInt64_SetLong(&leftval, left->value);
+ CInt64_SetLong(&rightval, right->value);
+ rightval = CMach_CalcIntDiadic(TYPE(&stsignedint), leftval, token, rightval);
+
+ if (left->xC) {
+ if (right->label)
+ PPCError_Error(124, left->xC->name->name, right->label->name->name);
+
+ if (right->xC) {
+ if (left->x10) {
+ PPCError_Error(121, left->xC->name->name, left->x10->name->name, right->xC->name->name);
+ } else if (right->x10) {
+ PPCError_Error(121, left->xC->name->name, right->xC->name->name, right->x10->name->name);
+ } else if (token == '-') {
+ left->value = CInt64_GetULong(&rightval);
+ left->x10 = right->xC;
+ } else {
+ IllegalObjectOperator(left->xC->name, right->xC->name, token);
+ }
+ } else if (token == '-' || token == '+') {
+ left->value = CInt64_GetULong(&rightval);
+ } else {
+ IllegalObjectOperator(left->xC->name, NULL, token);
+ }
+ } else if (right->xC) {
+ if (right->label)
+ PPCError_Error(124, right->xC->name->name, right->label->name->name);
+
+ if (token == '+') {
+ left->xC = right->xC;
+ left->x10 = right->x10;
+ left->value = CInt64_GetULong(&rightval);
+ } else {
+ IllegalObjectOperator(NULL, right->xC->name, token);
+ }
+ } else if (left->label) {
+ if (left->xC)
+ PPCError_Error(124, left->label->name->name, left->xC->name->name);
+
+ if (right->label) {
+ if (left->x18) {
+ PPCError_Error(121, left->label->name->name, left->x18->name->name, right->label->name->name);
+ } else if (right->x18) {
+ PPCError_Error(121, left->label->name->name, right->label->name->name, right->x18->name->name);
+ } else if (token == '-') {
+ left->value = CInt64_GetULong(&rightval);
+ left->x18 = right->label;
+ } else {
+ IllegalObjectOperator(left->label->name, right->label->name, token);
+ }
+ } else if (token == '+' || token == '-') {
+ left->value = CInt64_GetULong(&rightval);
+ } else {
+ IllegalObjectOperator(NULL, left->label->name, token);
+ }
+ } else if (right->label) {
+ if (token == '+') {
+ left->label = right->label;
+ left->x18 = right->x18;
+ left->value = CInt64_GetULong(&rightval);
+ } else {
+ IllegalObjectOperator(NULL, right->label->name, token);
+ }
+ } else {
+ left->value = CInt64_GetULong(&rightval);
+ }
+
+ left->flags |= right->flags;
+ if (left->type == IAOpnd_Lab) {
+ if (right->type != IAOpnd_Lab)
+ left->type = right->type;
+ } else {
+ if (right->type != IAOpnd_Lab && right->type != left->type)
+ PPCError_Error(126);
+ }
+}
+
+static void ExpressionTailPPC(IAExpr *left, SInt32 value) {
+ IAExpr right;
+ short left_tk;
+ short right_prec;
+
+ while (1) {
+ left_tk = tk;
+ tk = lex();
+
+ PrimaryExpressionPPC(&right, value);
+ right_prec = GetPrec(tk);
+ if (right_prec == 0) {
+ DiadicOperatorPPC(left, left_tk, &right);
+ break;
+ }
+
+ if (GetPrec(left_tk) >= right_prec) {
+ DiadicOperatorPPC(left, left_tk, &right);
+ } else {
+ ExpressionTailPPC(&right, value);
+ DiadicOperatorPPC(left, left_tk, &right);
+ if (GetPrec(tk) == 0)
+ break;
+ }
+ }
+}
+
+static void immediateoperand(IAOperand *op, SInt32 minval, SInt32 maxval) {
+ SInt32 value;
+ if (InlineAsm_gccmode && tk == '%') {
+ tk = lex();
+ if (tk != TK_INTCONST) {
+ CError_Error(CErrorStr144);
+ } else {
+ CInt64 c = tkintconst;
+ value = CInt64_GetULong(&c);
+ if (value < 0)
+ CError_Error(CErrorStr144);
+ }
+ op->type = IAOpnd_7;
+ op->u.unk7.value = value;
+ op->u.unk7.unk1 = 1;
+ op->u.unk7.unk2 = 0;
+ op->u.unk7.unk3 = 0;
+ tk = lex();
+ } else {
+ value = InlineAsm_ConstantExpressionPPC(0);
+ if (value < minval || value > maxval)
+ CError_Error(CErrorStr154);
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = value;
+ }
+}
+
+static SInt32 immediatevalue(IAOperand *op, SInt32 minval, SInt32 maxval) {
+ SInt32 value;
+ if (InlineAsm_gccmode && tk == '%') {
+ CError_Error(CErrorStr144);
+ return 0;
+ } else {
+ value = InlineAsm_ConstantExpressionPPC(0);
+ if (value < minval || value > maxval)
+ CError_Error(CErrorStr154);
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = value;
+ return value;
+ }
+}
+
+static void InlineAsm_ExpressionPPC(IAExpr *expr, SInt32 value) {
+ PrimaryExpressionPPC(expr, value);
+ if (GetPrec(tk))
+ ExpressionTailPPC(expr, value);
+ if (GetPrec(tk))
+ ExpressionTailPPC(expr, value);
+
+ if (expr->type == IAExpr_5 && tk == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "@l")) {
+ expr->type = IAExpr_6;
+ tk = lex();
+ } else if (!strcmp(tkidentifier->name, "@ha")) {
+ expr->type = IAExpr_8;
+ tk = lex();
+ } else if (!strcmp(tkidentifier->name, "@h")) {
+ expr->type = IAExpr_7;
+ tk = lex();
+ }
+ }
+}
+
+static SInt32 InlineAsm_ConstantExpressionPPC(SInt32 value) {
+ IAExpr expr;
+
+ InlineAsm_ExpressionPPC(&expr, value);
+ if (!InlineAsm_CheckExpr(&expr)) {
+ IllegalObjectInConst(&expr);
+ return 0;
+ } else {
+ return InlineAsm_GetExprValue(&expr);
+ }
+}
+
+static SInt32 crbitoperand(void) {
+ SInt32 value = InlineAsm_ConstantExpressionPPC(1);
+ if (value < 0 || value > 31)
+ CError_Error(CErrorStr154);
+ return value;
+}
+
+static void floatoperand(IAOperand *op, InlineAsm *ia, Type *type) {
+ Object *obj;
+
+ obj = createfloatconstant(type, &tkfloatconst);
+ op[0].type = IAOpnd_Reg;
+ op[0].u.reg.rclass = RegClass_GPR;
+ op[0].u.reg.object = NULL;
+ op[0].u.reg.effect = EffectRead;
+ op[0].u.reg.num = pic_base_reg;
+
+ ia->argcount++;
+ op[1].type = IAOpnd_4;
+ op[1].u.obj.obj = obj;
+ PPCError_Error(179);
+ op[1].u.obj.unk = IAExpr_2;
+ op[1].u.obj.offset = 0;
+ tk = lex();
+}
+
+static Object *isvariableoperand(void) {
+ IALookupResult result;
+ Object *obj;
+
+ if (tk == TK_IDENTIFIER) {
+ InlineAsm_LookupSymbol(tkidentifier, &result);
+ if ((obj = result.object)) {
+ if (obj->datatype == DLOCAL) {
+ if (OBJECT_REG(obj))
+ return NULL;
+ return obj;
+ }
+
+ if (obj->datatype == DFUNC || obj->datatype == DVFUNC)
+ return obj;
+
+ if (obj->datatype == DDATA) {
+ createIndirect(obj, 0, 0);
+ return obj;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static Object *isregisterstructpointeroperand(void) {
+ IALookupResult result;
+ Object *obj;
+
+ if (tk != TK_IDENTIFIER)
+ return NULL;
+
+ InlineAsm_LookupSymbol(tkidentifier, &result);
+ if ((obj = result.object)) {
+ if (obj->datatype != DLOCAL)
+ return NULL;
+ if (!OBJECT_REG(obj) && !is_register_object(obj))
+ return NULL;
+ if (!IS_TYPE_POINTER(obj->type))
+ return NULL;
+ if (!IS_TYPE_STRUCT(TPTR_TARGET(obj->type)) && !IS_TYPE_CLASS(TPTR_TARGET(obj->type)))
+ return NULL;
+ return obj;
+ }
+
+ return NULL;
+}
+
+static void memoryoperand(IAOperand *op, InlineAsm *ia, Boolean flag, short effect) {
+ IAExpr expr;
+
+ InlineAsm_ExpressionPPC(&expr, 0);
+ if (expr.object) {
+ if (!flag)
+ CError_Error(CErrorStr155);
+ if (expr.xC)
+ PPCError_Error(122, expr.xC);
+
+ op[0].type = IAOpnd_Reg;
+ op[0].u.reg.rclass = RegClass_GPR;
+ op[0].u.reg.object = expr.object;
+ op[0].u.reg.num = 0;
+ op[0].u.reg.effect = effect;
+ if (expr.object || expr.reg)
+ op[0].u.reg.effect = effect;
+ else
+ op[0].u.reg.effect = 0;
+
+ ia->argcount++;
+ op[1].type = IAOpnd_Imm;
+ switch (expr.type) {
+ case IAExpr_5:
+ expr.type = IAExpr_6;
+ if (expr.object->datatype != DLOCAL || !OBJECT_REG(expr.object))
+ PPCError_Error(180);
+ case IAExpr_2:
+ case IAExpr_6:
+ case IAExpr_7:
+ case IAExpr_8:
+ op[1].u.imm.value = InlineAsm_GetExprValue(&expr);
+ break;
+ default:
+ CError_Error(CErrorStr155);
+ }
+
+ expr.object->flags |= OBJECT_FLAGS_UNUSED;
+ return;
+ }
+
+ if (expr.xC) {
+ if (expr.x10)
+ PPCError_Error(123, expr.xC->name->name, expr.x10->name->name);
+
+ if (flag) {
+ if (tk == '(') {
+ if (flag) {
+ tk = lex();
+ registeroperand(op, RegClass_GPR, effect);
+ if ((expr.type == IAExpr_8 || expr.type == IAExpr_7) && copts.codegen_pic && pic_base_reg)
+ CError_Error(CErrorStr155);
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ tk = lex();
+ }
+ } else {
+ op[0].type = IAOpnd_Reg;
+ op[0].u.reg.rclass = RegClass_GPR;
+ op[0].u.reg.object = expr.object;
+ op[0].u.reg.num = expr.reg;
+ }
+
+ if (expr.object || expr.reg)
+ op[0].u.reg.effect = effect;
+ else
+ op[0].u.reg.effect = 0;
+
+ ia->argcount++;
+ op++;
+ }
+
+ if (expr.xC->datatype == DLOCAL) {
+ op[0].type = IAOpnd_4;
+ op[0].u.obj.unk = IAExpr_1;
+ } else {
+ op[0].type = IAOpnd_3;
+ if (expr.type == IAExpr_5) {
+ expr.type = IAExpr_6;
+ PPCError_Error(180);
+ }
+ op[0].u.obj.unk = expr.type;
+ }
+
+ op[0].u.obj.obj = expr.xC;
+ op[0].u.obj.offset = expr.value;
+ expr.xC->flags |= OBJECT_FLAGS_UNUSED;
+ return;
+ }
+
+ if (flag) {
+ if (tk == '(') {
+ tk = lex();
+ registeroperand(op, RegClass_GPR, effect);
+ ia->argcount++;
+ op++;
+ if (tk != ')')
+ CError_Error(CErrorStr115);
+ tk = lex();
+ } else {
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_GPR;
+ op->u.reg.object = expr.object;
+ op->u.reg.num = expr.reg;
+ ia->argcount++;
+ op++;
+ }
+ }
+
+ if (expr.label) {
+ if (expr.x18) {
+ op->type = IAOpnd_LabDiff;
+ op->negated = 0;
+ op->u.labdiff.label1 = expr.label;
+ op->u.labdiff.label2 = expr.x18;
+ op->u.labdiff.offset = expr.value;
+ } else {
+ PPCError_Error(125, expr.label->name->name);
+ }
+ } else {
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = InlineAsm_GetExprValue(&expr);
+ }
+}
+
+static void registeroperand(IAOperand *op, char rclass, short effect) {
+ IARegister *reg;
+ Object *obj;
+
+ if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupRegisterPPCName(tkidentifier)) && reg->rclass == rclass) {
+ SInt32 num;
+ obj = reg->object;
+ num = reg->num;
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = rclass;
+ op->u.reg.object = obj;
+ op->u.reg.num = num;
+ op->u.reg.effect = effect;
+ if (obj) {
+ reg->object->flags |= OBJECT_FLAGS_UNUSED;
+ Registers_GetVarInfo(obj)->flags |= VarInfoFlag40;
+ }
+ } else if (rclass == RegClass_CRFIELD) {
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_CRFIELD;
+ op->u.reg.object = NULL;
+ op->u.reg.num = getimmediateoperand(0, 7);
+ op->u.reg.effect = effect;
+ return;
+ } else if (rclass == RegClass_SPR) {
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.object = NULL;
+ op->u.reg.num = getimmediateoperand(0, 1024);
+ op->u.reg.effect = effect;
+ return;
+ } else if (tk == '%' && InlineAsm_gccmode) {
+ SInt32 num;
+ tk = lex();
+ if (tk != TK_INTCONST) {
+ CError_Error(CErrorStr144);
+ } else {
+ num = ExtractValue(tkintconst);
+ if (num < 0)
+ CError_Error(CErrorStr144);
+ }
+
+ op->type = IAOpnd_6;
+ op->u.unk6.num = num;
+ op->u.unk6.unk4 = 2;
+ op->u.unk6.effect = effect;
+ op->u.unk6.rclass = rclass;
+ tk = lex();
+ return;
+ } else if (tk == TK_IDENTIFIER) {
+ NotInRegisterError(tkidentifier->name, rclass);
+ } else {
+ PPCError_Error(171);
+ }
+
+ tk = lex();
+ if (!strcmp(tkidentifier->name, "@loword")) {
+ tk = lex();
+ } else if (!strcmp(tkidentifier->name, "@hiword")) {
+ if (reg->object)
+ op->u.reg.num = 1;
+ else
+ PPCError_Error(168);
+ tk = lex();
+ } else if (rclass == RegClass_GPR) {
+ if (reg->object && reg->object->type->size == 8) {
+ HashNameNode *name = reg->object->name;
+ PPCError_Error(127, name->name, name->name, name->name);
+ }
+ }
+}
+
+static void cr0_operand(IAOperand *op, short effect) {
+ IARegister *reg;
+
+ if ((reg = InlineAsm_LookupRegisterPPC("cr0"))) {
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_CRFIELD;
+ op->u.reg.object = reg->object;
+ op->u.reg.num = reg->num;
+ op->u.reg.effect = effect;
+ } else {
+ NotInRegisterError("cr0", RegClass_CRFIELD);
+ }
+}
+
+static void r0_operand(IAOperand *op) {
+ IARegister *reg;
+
+ if ((reg = InlineAsm_LookupRegisterPPC("r0"))) {
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_GPR;
+ op->u.reg.object = reg->object;
+ op->u.reg.num = reg->num;
+ op->u.reg.effect = 0;
+ tk = lex();
+ } else {
+ NotInRegisterError("r0", RegClass_GPR);
+ }
+}
+
+static void labeloperand(InlineAsm *ia, IAOperand *op, Boolean flag1, Boolean flag2, Boolean flag3) {
+ IALookupResult result;
+
+ if (tk == TK_IDENTIFIER) {
+ if (!InlineAsm_LookupSymbol(tkidentifier, &result))
+ result.label = InlineAsm_DeclareLabel(tkidentifier);
+
+ if (result.label) {
+ op->type = IAOpnd_Lab;
+ op->u.lab.label = result.label;
+ } else if (result.object && result.object->datatype == DFUNC) {
+ if (flag3)
+ ia->flags |= IAFlag2;
+ op->type = IAOpnd_3;
+ op->u.obj.obj = result.object;
+ op->u.obj.offset = 0;
+
+ if (flag1) {
+ op->u.obj.unk = IAExpr_4;
+ if (flag2)
+ CError_Error(CErrorStr261);
+ } else {
+ op->u.obj.unk = IAExpr_2;
+ if (flag2)
+ op->u.obj.unk = IAExpr_10;
+ op->u.obj.unk = IAExpr_6;
+ PPCError_Error(180);
+ }
+ } else {
+ CError_Error(CErrorStr144);
+ }
+
+ tk = lex();
+ } else if (tk == '*') {
+ if (!flag2) {
+ tk = lex();
+ if (tk == '+') {
+ tk = lex();
+ if (flag1)
+ immediateoperand(op, -0x2000000, 0x1FFFFFF);
+ else
+ immediateoperand(op, -0x8000, 0xFFFF);
+ } else if (tk == '-') {
+ tk = lex();
+ op->u.imm.value = flag1 ? -immediatevalue(op, -0x1FFFFFF, 0x2000000) : -immediatevalue(op, -0x7FFF, 0x10000);
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ } else {
+ if (flag2) {
+ if (flag1)
+ immediateoperand(op, -0x2000000, 0x1FFFFFF);
+ else
+ immediateoperand(op, -0x8000, 0xFFFF);
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ }
+}
+
+static void imm_or_labeldiff_operand(InlineAsm *ia, IAOperand *op, SInt32 minimum, SInt32 maximum, Boolean negate) {
+ IAExpr expr;
+ Object *obj;
+ SInt32 value;
+
+ InlineAsm_ExpressionPPC(&expr, 0);
+
+ if ((obj = expr.xC) && !expr.x10 && expr.type == IAExpr_5 && obj->datatype == DDATA && IS_TYPE_INT_OR_ENUM(obj->type) && (obj->qual & Q_10000)) {
+ switch (ia->opcode) {
+ case PC_ADDI:
+ case PC_ADDIC:
+ case PC_ADDICR:
+ case PC_ADDIS:
+ case PC_ORI:
+ case PC_ORIS:
+ if (ia->args[1].u.imm.value) {
+ SInt32 cmp;
+ if (obj->datatype != DLOCAL) {
+ cmp = copts.codegen_pic ? INVALID_PIC_REG : NO_REG;
+ } else {
+ cmp = local_base_register(obj);
+ }
+ if (ia->args[1].u.imm.value == cmp)
+ break;
+ }
+ case PC_LI:
+ case PC_LIS:
+ case PC_TWI:
+ case PC_OPWORD:
+ InlineAsm_InitExpr5(&expr, expr.value + CInt64_GetULong(&obj->u.data.u.intconst));
+ break;
+ }
+ }
+
+ if (expr.label) {
+ if (expr.x18) {
+ op->type = IAOpnd_LabDiff;
+ if (negate)
+ op->negated = 1;
+ else
+ op->negated = 0;
+ op->u.labdiff.label1 = expr.label;
+ op->u.labdiff.label2 = expr.x18;
+ op->u.labdiff.offset = expr.value;
+ } else {
+ PPCError_Error(125, expr.label->name->name);
+ }
+ return;
+ }
+
+ if (expr.xC) {
+ if (!expr.x10) {
+ if (ia->opcode != PC_OPWORD && expr.type == IAExpr_5) {
+ IllegalObjectInConst(&expr);
+ return;
+ }
+
+ if (expr.xC->datatype == DLOCAL) {
+ op->type = IAOpnd_4;
+ op->u.obj.unk = IAExpr_1;
+ } else {
+ op->type = IAOpnd_3;
+ if (expr.type == IAExpr_5) {
+ expr.type = IAExpr_6;
+ PPCError_Error(180);
+ }
+ op->u.obj.unk = expr.type;
+ }
+ op->u.obj.obj = expr.xC;
+ op->u.obj.offset = expr.value;
+ } else {
+ PPCError_Error(123, expr.xC->name->name, expr.x10->name->name);
+ }
+ return;
+ }
+
+ value = InlineAsm_GetExprValue(&expr);
+ if (value < minimum || value > maximum)
+ CError_Error(CErrorStr154);
+
+ op->type = IAOpnd_Imm;
+ if (negate)
+ op->u.imm.value = -value;
+ else
+ op->u.imm.value = value;
+}
+
+static void eatcommatoken(void) {
+ if (tk == ',')
+ tk = lex();
+ else
+ CError_Error(CErrorStr116);
+}
+
+static InlineAsm *InlineAsm_ScanAssemblyOperands(IAMnemonic *mnemonic) {
+ OpcodeInfo *info;
+ InlineAsm *ia;
+ SInt32 buffersize;
+ IAOperand *op;
+ int argcount;
+ char *format;
+ IARegister *reg;
+
+ char code;
+ short effect;
+ Boolean has_excl;
+ Boolean has_question;
+ Boolean negate;
+ UInt32 t;
+
+ info = &opcodeinfo[mnemonic->x4];
+ argcount = info->x8;
+ if (PCODE_FLAG_SET_F(info) & fPCodeFlag8000000)
+ argcount++;
+ if (!(PCODE_FLAG_SET_F(info) & fPCodeFlag10000000) && (PCODE_FLAG_SET_F(info) & fPCodeFlag4000000))
+ argcount++;
+ if (PCODE_FLAG_SET_T(info) & fPCodeFlag2000000)
+ argcount++;
+
+ buffersize = sizeof(InlineAsm) + sizeof(IAOperand) * argcount;
+ ia = galloc(buffersize);
+ memset(ia, 0, buffersize);
+
+ ia->opcode = mnemonic->x4;
+ ia->flags = 0;
+ ia->argcount = 0;
+
+ op = ia->args;
+ for (format = mnemonic->format; *format; format++) {
+#line 1664
+ CError_ASSERT(ia->argcount < argcount);
+
+ if (*format == ',') {
+ eatcommatoken();
+ format++;
+ } else if (*format == ';') {
+ format++;
+ }
+
+ if (*format == '[' || *format == '(')
+ format++;
+
+ effect = EffectRead;
+ has_excl = 0;
+ has_question = 0;
+ negate = 0;
+ if (*format == '=') {
+ effect = EffectWrite;
+ format++;
+ } else if (*format == '+') {
+ effect = EffectRead | EffectWrite;
+ format++;
+ }
+
+ if (*format == '-') {
+ negate = 1;
+ format++;
+ }
+
+ if (*format == '?') {
+ has_question = 1;
+ format++;
+ }
+
+ if (*format == '!') {
+ has_excl = 1;
+ format++;
+ }
+
+ switch (*format) {
+ case 'p':
+ continue;
+ case '&':
+ if (format[1] == '2') {
+ op[0] = op[-2];
+ format++;
+ if (op->type == IAOpnd_Reg)
+ op->u.reg.effect = effect;
+ ia->argcount++;
+
+ op[1] = op[-1];
+ op++;
+ if (op->type == IAOpnd_Reg)
+ op->u.reg.effect = effect;
+ } else {
+ op[0] = op[-1];
+ if (op->type == IAOpnd_Reg)
+ op->u.reg.effect = effect;
+ }
+ break;
+
+ case '%': {
+ SInt32 value;
+ format += pcode_const_from_format(format + 1, &value);
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = value;
+ break;
+ }
+
+ case 'b':
+ if (!isregisteroperand(RegClass_GPR)) {
+ if (tk == TK_INTCONST && tkintconst.lo == 0)
+ r0_operand(op);
+ } else {
+ registeroperand(op, RegClass_GPR, effect);
+ if (op->u.reg.object == NULL && op->u.reg.num == 0)
+ op->u.reg.effect = 0;
+ }
+ break;
+
+ case 'r':
+ registeroperand(op, RegClass_GPR, effect);
+ break;
+
+ case 'B':
+ case 'a':
+ case 'i':
+ case 't':
+ case 'u':
+ case 'x':
+ {
+ SInt32 value, hi, lo;
+ code = *format;
+ value = 16;
+ if (code == 'a') {
+ if (isdigit(format[1])) {
+ code = *(++format);
+ } else {
+#line 1804
+ CError_FATAL();
+ }
+ }
+
+ if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &value);
+ } else if (code == 't' || code == 'B') {
+ code = 'u';
+ value = 5;
+ }
+
+ pcode_get_hi_lo(value, code, &hi, &lo);
+ if (!has_question || tk == ',') {
+ if (has_question)
+ tk = lex();
+ if (has_excl)
+ getimmediateoperand(lo, hi);
+ else
+ immediateoperand(op, lo, hi);
+ } else {
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = 0;
+ }
+
+ if (code == 'i' && value == 16)
+ op->u.imm.value = (short) op->u.imm.value;
+ if (negate)
+ op->u.imm.value = -op->u.imm.value;
+
+ if (pcode_check_imm_bits(op->u.imm.value, value, code)) {
+#line 1838
+ CError_FATAL();
+ }
+
+ break;
+ }
+
+ case 'O':
+ if (tk == TK_INTCONST && tkintconst.lo == 0) {
+ getimmediateoperand(0, 0);
+ eatcommatoken();
+ }
+ continue;
+
+ case 'f':
+ registeroperand(op, RegClass_FPR, effect);
+ break;
+
+ case 'v':
+ registeroperand(op, RegClass_VR, effect);
+ break;
+
+ case 'T':
+ if (!has_question || tk == ',') {
+ if (has_question)
+ tk = lex();
+
+ immediateoperand(op, 268, 269);
+ if (op->u.reg.num == 268)
+ op->u.reg.num = 284;
+ else
+ op->u.reg.num = 285;
+ } else {
+ op->u.reg.num = 284;
+ }
+
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.effect = effect;
+ break;
+
+ case 'S':
+ {
+ SInt32 value;
+ format += pcode_const_from_format(format + 1, &value);
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.num = value;
+ op->u.reg.effect = effect;
+ break;
+ }
+
+ case 'c':
+ if (has_question) {
+ if (isregisteroperand(RegClass_CRFIELD) || tk == TK_INTCONST) {
+ registeroperand(op, RegClass_CRFIELD, effect);
+ } else {
+ cr0_operand(op, effect);
+ if (format[1] == ',')
+ format++;
+ }
+ } else {
+ registeroperand(op, RegClass_CRFIELD, effect);
+ }
+ break;
+
+ case 'l':
+ switch (ia->opcode) {
+ case PC_B:
+ case PC_BL:
+ labeloperand(ia, op, 1, mnemonic->x10 & 2, mnemonic->x10 & 1);
+ break;
+ default:
+ labeloperand(ia, op, 0, mnemonic->x10 & 2, mnemonic->x10 & 1);
+ break;
+ }
+ break;
+
+ case 'w':
+ imm_or_labeldiff_operand(ia, op, -0x80000000, 0x7FFFFFFF, negate);
+ break;
+
+ case 'M':
+ case 'm':
+ case 'n':
+ imm_or_labeldiff_operand(ia, op, -0x8000, 0xFFFF, negate);
+ break;
+
+ case 'Q':
+ {
+ SInt32 cr = crbitoperand();
+ op->type = IAOpnd_Reg;
+ op->u.reg.num = cr >> 2;
+ op->u.reg.rclass = RegClass_CRFIELD;
+ op->u.reg.effect = effect;
+
+ ia->argcount++;
+ op[1].type = IAOpnd_Imm;
+ op[1].u.imm.value = cr % 4;
+ op++;
+ break;
+ }
+
+ case 'd': {
+ short effect2;
+#line 1971
+ CError_ASSERT(format[1] == '(');
+ format++;
+ effect2 = EffectRead;
+ if (format[1] == '=') {
+ effect2 = EffectWrite;
+ format++;
+ } else if (format[1] == '+') {
+ effect2 = EffectRead | EffectWrite;
+ format++;
+ }
+
+#line 1983
+ CError_ASSERT(format[1] == 'b');
+#line 1985
+ CError_ASSERT(format[2] == ')');
+ format += 2;
+
+ switch (ia->opcode) {
+ case PC_LFS:
+ if (tk == TK_FLOATCONST)
+ floatoperand(op, ia, TYPE(&stfloat));
+ else
+ memoryoperand(op, ia, 1, effect2);
+ break;
+ case PC_LFD:
+ if (tk == TK_FLOATCONST)
+ floatoperand(op, ia, TYPE(&stdouble));
+ else
+ memoryoperand(op, ia, 1, effect2);
+ break;
+ default:
+ memoryoperand(op, ia, 1, effect2);
+ }
+
+ break;
+ }
+
+ case 'N':
+ immediateoperand(op, 1, 32);
+ break;
+
+ case 's':
+ registeroperand(op, RegClass_SPR, effect);
+ break;
+
+ case 'D':
+ if (tk == TK_IDENTIFIER && (reg = InlineAsm_LookupDCRRegister(tkidentifier->name))) {
+ op->type = IAOpnd_Imm;
+ op->u.imm.value = reg->num;
+ } else {
+ immediateoperand(op, 0, 1023);
+ }
+ break;
+
+ case 'Y':
+ {
+ SInt32 mask = 255;
+ SInt32 i;
+ if (ia->opcode == PC_MTCRF) {
+ if (ia->args[0].type != IAOpnd_Imm)
+ CError_Error(CErrorStr144);
+ mask = ia->args[0].u.imm.value;
+ }
+ for (i = 0; i < 8; i++) {
+ if ((0x80 >> i) & mask) {
+ op->type = IAOpnd_Reg;
+ op->u.reg.num = i;
+ op->u.reg.rclass = RegClass_CRFIELD;
+ op->u.reg.effect = effect;
+ ia->argcount++;
+ op++;
+ }
+ }
+ ia->argcount--;
+ op--;
+ break;
+ }
+
+ case 'P':
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.object = NULL;
+ if (format[1] == '3') {
+ format++;
+ op->u.reg.num = getimmediateoperand(0, 7);
+ } else {
+ op->u.reg.num = getimmediateoperand(0, 3);
+ }
+ op->u.reg.effect = effect;
+ break;
+
+ case 'C':
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.object = NULL;
+ op->u.reg.num = 9;
+ op->u.reg.effect = effect;
+ break;
+
+ case 'L':
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.object = NULL;
+ op->u.reg.num = 8;
+ op->u.reg.effect = effect;
+ break;
+
+ case 'X':
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_SPR;
+ op->u.reg.object = NULL;
+ op->u.reg.num = 1;
+ op->u.reg.effect = effect;
+ break;
+
+ case 'Z':
+ op->type = IAOpnd_Reg;
+ op->u.reg.rclass = RegClass_CRFIELD;
+ op->u.reg.object = NULL;
+ t = info->flags & 0xC0000000;
+ if (t == 0x40000000) {
+ op->u.reg.num = 1;
+ } else if (t == 0xC0000000) {
+ op->u.reg.num = 6;
+ } else {
+ op->u.reg.num = 0;
+ }
+ op->u.reg.effect = effect;
+ break;
+
+ default:
+#line 2266
+ CError_FATAL();
+ }
+
+ while (format[1] && strchr("/<>|*", format[1])) {
+ int index;
+ SInt32 value;
+ SInt32 value2;
+ IAOperand tmp;
+ switch ((code = *(++format))) {
+ case '/':
+ index = -1;
+ if (format[1] == '2') {
+ index = -2;
+ format++;
+ }
+
+ tmp = op[index];
+ op[index] = op[0];
+ op[0] = tmp;
+ break;
+ case '*':
+ case '<':
+ case '>':
+ case '|':
+ if (op->type == IAOpnd_Imm) {
+ value = op->u.imm.value;
+ } else if (op->type == IAOpnd_Reg) {
+ value = op->u.reg.num;
+ } else {
+#line 2312
+ CError_FATAL();
+ }
+
+ if (format[1] == 'p') {
+ format++;
+ if (op[-1].type == IAOpnd_Imm) {
+ value2 = op[-1].u.imm.value;
+ } else if (op[-1].type == IAOpnd_Reg) {
+ value2 = op[-1].u.reg.num;
+ } else {
+#line 2322
+ CError_FATAL();
+ }
+ } else if (isdigit(format[1])) {
+ format += pcode_const_from_format(format + 1, &value2);
+ } else {
+#line 2327
+ CError_FATAL();
+ }
+
+ switch (code) {
+ case '<':
+ value = value2 - value;
+ break;
+ case '>':
+ value = value - value2;
+ break;
+ case '|':
+ value = value + value2;
+ break;
+ case '*':
+ value = value * value2;
+ break;
+ default:
+#line 2348
+ CError_FATAL();
+ }
+
+ if (op->type == IAOpnd_Imm) {
+ op->u.imm.value = value;
+ } else if (op->type == IAOpnd_Reg) {
+ op->u.reg.num = value;
+ } else {
+#line 2355
+ CError_FATAL();
+ }
+ break;
+ }
+ }
+
+ ia->argcount++;
+ op++;
+ if (format[1] == ']' || format[1] == ')')
+ format++;
+ }
+
+ return ia;
+}
+
+static int mnemonic_has_overflow(char *buf) {
+ int result = 0;
+
+ if (buf[strlen(buf) - 1] == 'o') {
+ if (!strcmp(buf, "bso"))
+ return 0;
+ if (!strcmp(buf, "fcmpo"))
+ return 0;
+ if (!strcmp(buf, "eieio"))
+ return 0;
+ if (!strcmp(buf, "vslo"))
+ return 0;
+ if (!strcmp(buf, "vsro"))
+ return 0;
+ result = 1;
+ }
+
+ return result;
+}
+
+static int mnemonic_has_absolute(char *buf) {
+ int result = 0;
+ char last = buf[strlen(buf) - 1];
+
+ if (buf[0] == 'b' && last == 'a')
+ result = 1;
+
+ return result;
+}
+
+static int mnemonic_has_linkregister(char *buf) {
+ int result = 0;
+ char last = buf[strlen(buf) - 1];
+
+ if (buf[0] == 'b' && last == 'l')
+ result = 1;
+
+ return result;
+}
+
+static int mnemonic_has_record(char *buf) {
+ int result = 0;
+
+ if (lookahead() == '.') {
+ tk = lex();
+ result = 1;
+ strcat(buf, ".");
+ }
+
+ return result;
+}
+
+static void installregistervariables(void) {
+}
+
+void InlineAsm_InitializePPC(void) {
+ Test_Version_Numbers();
+ allow_array_expressions = 1;
+ supports_hardware_fpu = 1;
+ assembledinstructions = 0;
+
+ switch (copts.cpu) {
+ case CPU_PPC401: cpu = CPUMask_401; break;
+ case CPU_PPC403: cpu = CPUMask_403; break;
+ case CPU_PPC505: cpu = CPUMask_50x; break;
+ case CPU_PPC509: cpu = CPUMask_50x; break;
+ case CPU_PPC555: cpu = CPUMask_55x_56x; break;
+ case CPU_PPC556: cpu = CPUMask_55x_56x; break;
+ case CPU_PPC565: cpu = CPUMask_55x_56x; break;
+ case CPU_PPC601: cpu = CPUMask_601; break;
+ case CPU_PPC602: cpu = CPUMask_602; break;
+ case CPU_PPC8240: cpu = CPUMask_8240; break;
+ case CPU_PPC8260: cpu = CPUMask_8260; break;
+ case CPU_PPC603: cpu = CPUMask_603; break;
+ case CPU_PPC603e: cpu = CPUMask_603; break;
+ case CPU_PPC604: cpu = CPUMask_604; break;
+ case CPU_PPC604e: cpu = CPUMask_604; break;
+ case CPU_PPC740: cpu = CPUMask_740_750; break;
+ case CPU_PPC750: cpu = CPUMask_740_750; break;
+ case CPU_PPC801: cpu = CPUMask_801_821_860; break;
+ case CPU_PPC821: cpu = CPUMask_801_821_860; break;
+ case CPU_PPC823: cpu = CPUMask_823_850; break;
+ case CPU_PPC850: cpu = CPUMask_823_850; break;
+ case CPU_PPC860: cpu = CPUMask_801_821_860; break;
+ case CPU_PPC7400: case CPU_PPC7450: cpu = CPUMask_74xx; break;
+ case CPU_Generic: cpu = CPUMask_Generic; break;
+ default:
+#line 2613
+ CError_FATAL();
+ }
+
+ if (copts.altivec_model)
+ cpu |= 0x40000000;
+}
+
+void InlineAsm_Initialize(UInt8 assemblertype) {
+ assembler_type = assemblertype;
+
+ if (assembler_type == 0) {
+ InlineAsm_InitializePPC();
+ pic_base_reg = INVALID_PIC_REG;
+ } else {
+ pic_base_reg = 0;
+ pic_base_label = NULL;
+ }
+
+ InlineAsm_InitializeMnemonicsPPC();
+ InlineAsm_InitializeRegisters();
+ InlineAsm_InitializeRegistersPPC();
+
+ if (assembler_type == 0) {
+ installregistervariables();
+ } else {
+ process_arguments(setup_assembly_argument, 0);
+ assign_local_addresses();
+ }
+}
+
+static IAEntryPoint *InlineAsm_CreateEntryPoint(HashNameNode *name, Boolean flag) {
+ Object *obj;
+ IAEntryPoint *ep;
+ IALookupResult result;
+
+ if (InlineAsm_LookupSymbol(name, &result) && (obj = result.object)) {
+ if (!(obj->datatype == DFUNC && !(obj->flags & OBJECT_FLAGS_4)))
+ CError_Error(CErrorStr122, name->name);
+
+ obj->flags |= OBJECT_FLAGS_4;
+ obj->sclass = flag ? TK_STATIC : TK_EXTERN;
+
+ ep = lalloc(sizeof(IAEntryPoint));
+ memclrw(ep, sizeof(IAEntryPoint));
+ ep->x0 = IADirective_Entry;
+ ep->x2 = 1;
+ ep->x8 = obj;
+ ep->size = assembledinstructions * 4;
+ } else {
+ CError_Error(CErrorStr140, name->name);
+ }
+
+ return ep;
+}
+
+static InlineAsm *InlineAsm_CreateFrFree(void) {
+ InlineAsm *ia = lalloc(sizeof(InlineAsm));
+ memclrw(ia, sizeof(InlineAsm));
+ ia->opcode = IADirective_FrFree;
+ ia->flags = IAFlag1;
+ return ia;
+}
+
+SInt32 InlineAsm_IsDirective(UInt8 assemblertype) {
+ char *name;
+ SInt32 directive = IADirective_Null;
+
+ if (tk == '.')
+ tk = lex();
+
+ if (tk == TK_IDENTIFIER) {
+ name = tkidentifier->name;
+ if (!strcmp(name, "machine")) {
+ directive = IADirective_Machine;
+ } else if (assemblertype == 1) {
+ if (!strcmp(name, "entry")) {
+ directive = IADirective_Entry;
+ } else if (!strcmp(name, "fralloc")) {
+ directive = IADirective_FrAlloc;
+ } else if (!strcmp(name, "nofralloc")) {
+ directive = IADirective_NoFrAlloc;
+ } else if (!strcmp(name, "frfree")) {
+ directive = IADirective_FrFree;
+ } else if (!strcmp(name, "smclass")) {
+ directive = IADirective_SmClass;
+ } else if (!strcmp(name, "picbase")) {
+ directive = IADirective_PicBase;
+ } else {
+ directive = IADirective_Null;
+ }
+ }
+ }
+
+ return directive;
+}
+
+void InlineAsm_ProcessDirective(SInt32 directive) {
+ Boolean flag;
+ Statement *stmt;
+ IAOperand op;
+
+ switch (directive) {
+ case IADirective_Entry:
+ flag = 0;
+ tk = lex();
+ if (tk == TK_STATIC) {
+ flag = 1;
+ tk = lex();
+ } else if (tk == TK_EXTERN) {
+ tk = lex();
+ }
+
+ if (tk != TK_IDENTIFIER)
+ CError_Error(CErrorStr107);
+
+ stmt = CFunc_AppendStatement(ST_ASM);
+ stmt->expr = NULL;
+ stmt->expr = (ENode *) InlineAsm_CreateEntryPoint(tkidentifier, flag);
+ stmt->sourceoffset = -1;
+ tk = lex();
+ break;
+
+ case IADirective_FrAlloc:
+ if (assembledinstructions)
+ CError_Error(CErrorStr166);
+ if (asm_alloc_flags[0])
+ CError_Error(CErrorStr165);
+ if (asm_alloc_flags[1] || asm_alloc_flags[2])
+ CError_Error(CErrorStr166);
+
+ tk = lex();
+ if (tk != TK_NEG7 && tk != ';')
+ fralloc_parameter_area_size = getimmediateoperand(0x20, 0x7FFE);
+
+ requires_frame = 1;
+ asm_alloc_flags[0] = 1;
+ break;
+
+ case IADirective_NoFrAlloc:
+ if (asm_alloc_flags[0] || asm_alloc_flags[1])
+ CError_Error(CErrorStr165);
+ if (asm_alloc_flags[2])
+ CError_Error(CErrorStr166);
+ if (assembledinstructions)
+ CError_Error(CErrorStr166);
+ tk = lex();
+
+ asm_alloc_flags[1] = 1;
+ user_responsible_for_frame = 1;
+ break;
+
+ case IADirective_FrFree:
+ if (asm_alloc_flags[1] || asm_alloc_flags[2])
+ CError_Error(CErrorStr166);
+
+ asm_alloc_flags[2] = 1;
+ stmt = CFunc_AppendStatement(ST_ASM);
+ stmt->expr = NULL;
+ stmt->expr = (ENode *) InlineAsm_CreateFrFree();
+ if (copts.isGeneratingDebugInfo)
+ stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset);
+ else
+ stmt->sourceoffset = -1;
+ tk = lex();
+ break;
+
+ case IADirective_Machine:
+ tk = lex();
+ if (tk == TK_INTCONST) {
+ switch (tkintconst.lo) {
+ case 401: cpu = CPUMask_401; break;
+ case 403: cpu = CPUMask_403; break;
+ case 505: cpu = CPUMask_50x; break;
+ case 509: cpu = CPUMask_50x; break;
+ case 555: cpu = CPUMask_55x_56x; break;
+ case 556: cpu = CPUMask_55x_56x; break;
+ case 565: cpu = CPUMask_55x_56x; break;
+ case 601: cpu = CPUMask_601; break;
+ case 602: cpu = CPUMask_602; break;
+ case 8240: cpu = CPUMask_8240; break;
+ case 8260: cpu = CPUMask_8260; break;
+ case 603: cpu = CPUMask_603; break;
+ case 604: cpu = CPUMask_604; break;
+ case 740: cpu = CPUMask_740_750; break;
+ case 750: cpu = CPUMask_740_750; break;
+ case 801: cpu = CPUMask_801_821_860; break;
+ case 821: cpu = CPUMask_801_821_860; break;
+ case 823: cpu = CPUMask_823_850; break;
+ case 850: cpu = CPUMask_823_850; break;
+ case 860: cpu = CPUMask_801_821_860; break;
+ case 7400: cpu = CPUMask_74xx; break;
+ default:
+ CError_Error(CErrorStr144);
+ }
+ } else if (tk == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "all")) {
+ cpu = CPUMask_All;
+ } else if (!strcmp(tkidentifier->name, "generic")) {
+ cpu = CPUMask_Generic;
+ } else if (!strcmp(tkidentifier->name, "603e")) {
+ cpu = CPUMask_603;
+ } else if (!strcmp(tkidentifier->name, "604e")) {
+ cpu = CPUMask_604;
+ } else if (!strcmp(tkidentifier->name, "PPC603e")) {
+ cpu = CPUMask_603;
+ } else if (!strcmp(tkidentifier->name, "PPC604e")) {
+ cpu = CPUMask_604;
+ } else if (!strcmp(tkidentifier->name, "altivec")) {
+ cpu = CPUMask_74xx;
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ tk = lex();
+ break;
+
+ case IADirective_SmClass:
+ tk = lex();
+ if (tk == TK_IDENTIFIER) {
+ if (!strcmp(tkidentifier->name, "PR"))
+ sm_section = 1;
+ else
+ CError_Error(CErrorStr144);
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ tk = lex();
+ break;
+
+ case IADirective_PicBase:
+ tk = lex();
+ registeroperand(&op, RegClass_GPR, EffectRead);
+
+ if (!(op.type == IAOpnd_Reg && op.u.reg.object == NULL))
+ CError_Error(CErrorStr144);
+
+ tk = lex();
+ if (tk == TK_IDENTIFIER) {
+ savepicbase(op.u.reg.num, tkidentifier);
+ tk = lex();
+ } else {
+ CError_Error(CErrorStr144);
+ }
+ break;
+
+ default:
+ CError_Error(CErrorStr261);
+ }
+}
+
+void InlineAsm_ScanAssemblyDirective(void) {
+ SInt32 directive;
+
+ if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null)
+ InlineAsm_ProcessDirective(directive);
+}
+
+void InlineAsm_ScanAssemblyInstruction(void) {
+ Statement *stmt;
+ InlineAsm *ia;
+ IAMnemonic *mnemonic;
+ Boolean record_flag;
+ Boolean flag3;
+ Boolean flag4;
+ Boolean flag5;
+ Boolean flag1;
+ Boolean flag2;
+ SInt32 directive;
+ char buf[20];
+
+ flag1 = 0;
+ flag2 = 0;
+ if ((directive = InlineAsm_IsDirective(assembler_type)) != IADirective_Null) {
+ InlineAsm_ProcessDirective(directive);
+ return;
+ }
+
+ stmt = CFunc_AppendStatement(ST_ASM);
+ stmt->expr = NULL;
+ if (copts.isGeneratingDebugInfo)
+ stmt->sourceoffset = CPrep_GetFileOffsetInfo(&cparser_fileoffset);
+ else
+ stmt->sourceoffset = -1;
+
+ strncpy(buf, tkidentifier->name, sizeof(buf));
+ record_flag = mnemonic_has_record(buf);
+ mnemonic = InlineAsm_LookupMnemonicPPC(buf);
+ if (!mnemonic)
+ CError_Error(CErrorStr261);
+
+ flag3 = (FLAG_SET_F(opcodeinfo[mnemonic->x4].flags) & fPCodeFlag4000000) && (mnemonic->x10 & 0x400);
+ flag4 = (FLAG_SET_T(opcodeinfo[mnemonic->x4].flags) & fPCodeFlag20000000) && (mnemonic->x10 & 2);
+ flag5 = (FLAG_SET_T(opcodeinfo[mnemonic->x4].flags) & fPCodeFlag2000000) && (mnemonic->x10 & 1);
+
+ if ((cpu == CPUMask_Generic) && (cpu & CPUFLAG_LOW_MASK) != ((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK)) {
+ CError_Error(CErrorStr152);
+ } else if (((cpu & mnemonic->cpu) & CPUFLAG_LOW_MASK) == 0) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_10000000) && !(cpu & CPUFLAG_10000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_8000000) && !(cpu & CPUFLAG_8000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_2000000) && !(cpu & CPUFLAG_2000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_4000000) && !(cpu & CPUFLAG_4000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_1000000) && !(cpu & CPUFLAG_1000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_40000000) && !(cpu & CPUFLAG_40000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_20000000) && !(cpu & CPUFLAG_20000000)) {
+ CError_Error(CErrorStr152);
+ } else if ((mnemonic->cpu & CPUFLAG_800000) && !(cpu & CPUFLAG_800000)) {
+ CError_Error(CErrorStr152);
+ }
+
+ tk = lex();
+ if (tk == '+' || tk == '-') {
+ if (
+ ((OPCODE_PART_1(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20)) ||
+ ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 528) && (OPCODE_PART_2(mnemonic->x10) != 20)) ||
+ ((OPCODE_PART_1(mnemonic->x10) == 19) && (OPCODE_PART_3(mnemonic->x10) == 16) && (OPCODE_PART_2(mnemonic->x10) != 20))
+ ) {
+ if (tk == '+')
+ flag1 = 1;
+ else if (tk == '-')
+ flag2 = 1;
+ tk = lex();
+ } else {
+ CError_Error(CErrorStr120);
+ }
+ }
+
+ stmt->expr = (ENode *) InlineAsm_ScanAssemblyOperands(mnemonic);
+
+ ia = (InlineAsm *) stmt->expr;
+ if (record_flag)
+ ia->flags2 |= IAFlagsB_1;
+ if (flag3)
+ ia->flags2 |= IAFlagsB_2;
+ if (flag4)
+ ia->flags2 |= IAFlagsB_4;
+ if (flag5)
+ ia->flags2 |= IAFlagsB_8;
+ if (flag1)
+ ia->flags2 |= IAFlagsB_10;
+ if (flag2)
+ ia->flags2 |= IAFlagsB_20;
+ if (volatileasm)
+ ia->flags2 |= IAFlagsB_40;
+
+ ++assembledinstructions;
+}
+
+static PCode *InlineAsm_TranslateIRtoPCodePPC(InlineAsm *ia, int argcount, UInt8 assemblertype) {
+ OpcodeInfo *info;
+ PCode *pc;
+ int index;
+ int extra_args;
+ int reg;
+ int newargcount;
+ SInt32 buffersize;
+ IAOperand *src;
+ PCodeArg *dest;
+
+ info = &opcodeinfo[ia->opcode];
+ index = 0;
+ extra_args = 0;
+ reg = 0;
+
+ if ((PCODE_FLAG_SET_F(info) & fPCodeFlag8000000) && !(PCODE_FLAG_SET_F(info) & fPCodeFlag20000000))
+ extra_args++;
+
+ if (!(PCODE_FLAG_SET_F(info) & fPCodeFlag10000000) && (PCODE_FLAG_SET_F(info) & fPCodeFlag4000000))
+ extra_args++;
+
+ if (argcount < ia->argcount) {
+ if ((argcount + extra_args) >= ia->argcount) {
+ extra_args -= (ia->argcount - argcount);
+ argcount = ia->argcount;
+ } else {
+#line 3317
+ CError_FATAL();
+ }
+ }
+
+ if (ia->opcode == PC_B && ia->args[0].type == IAOpnd_Imm)
+ ia->flags2 |= IAFlagsB_40;
+
+ if (ia->opcode == PC_TWI || ia->opcode == PC_TW || ia->opcode == PC_TRAP || ia->opcode == PC_SC)
+ ia->flags |= IAFlag2;
+
+ if (ia->flags & IAFlag2) {
+ newargcount = argcount + branch_count_volatiles();
+ if (copts.exceptions && current_statement && assembler_type == 0)
+ newargcount += countexceptionactionregisters(current_statement->dobjstack);
+
+ buffersize = sizeof(PCode) + sizeof(PCodeArg) * (newargcount + extra_args);
+ pc = lalloc(buffersize);
+ memset(pc, 0, buffersize);
+ pc->argCount = newargcount;
+ } else if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) {
+ reg = ia->args[0].u.reg.object ? OBJECT_REG(ia->args[0].u.reg.object) : ia->args[0].u.reg.num;
+ newargcount = argcount + (32 - reg);
+
+ buffersize = sizeof(PCode) + sizeof(PCodeArg) * newargcount;
+ pc = lalloc(buffersize);
+ memset(pc, 0, buffersize);
+ pc->argCount = newargcount;
+ } else {
+ buffersize = sizeof(PCode) + sizeof(PCodeArg) * (argcount + extra_args);
+ pc = lalloc(buffersize);
+ memset(pc, 0, buffersize);
+ pc->argCount = (ia->argcount > argcount) ? ia->argcount : argcount;
+ }
+
+ pc->op = ia->opcode;
+ pc->flags = info->flags;
+ pc->sourceoffset = current_statement ? current_statement->sourceoffset : -1;
+
+ dest = pc->args;
+ src = ia->args;
+ argcount += extra_args;
+ while (index < argcount) {
+ if (index >= ia->argcount) {
+ dest->kind = PCOp_PLACEHOLDEROPERAND;
+ } else {
+ switch (src->type) {
+ case IAOpnd_0:
+ dest->kind = PCOp_PLACEHOLDEROPERAND;
+ break;
+
+ case IAOpnd_Imm:
+ dest->kind = PCOp_IMMEDIATE;
+ dest->data.imm.value = src->u.imm.value;
+ if (pc->flags & (fPCodeFlag2 | fPCodeFlag4))
+ pc->flags |= fPCodeFlag20;
+ dest->data.imm.obj = NULL;
+ break;
+
+ case IAOpnd_Reg: {
+ int r20;
+ r20 = 0;
+ if (src->u.reg.object) {
+ if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag2) {
+ if (src->u.reg.num == 1)
+ r20 = OBJECT_REG_HI(src->u.reg.object);
+ else
+ r20 = OBJECT_REG(src->u.reg.object);
+ } else {
+ if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag40)
+ PPCError_Error(172, src->u.reg.object->name->name);
+ else
+ PPCError_Error(167, src->u.reg.object->name->name);
+ }
+ } else if (src->u.reg.num == INVALID_PIC_REG) {
+ r20 = pic_base_reg;
+ } else {
+ r20 = src->u.reg.num;
+ }
+
+ dest->kind = PCOp_REGISTER;
+ dest->arg = src->u.reg.rclass;
+ dest->data.reg.reg = r20;
+ dest->data.reg.effect = src->u.reg.effect;
+ if (pc->op == PC_RLWIMI && (dest->data.reg.effect & EffectWrite) && dest->arg == RegClass_GPR && !(dest->data.reg.effect & EffectRead)) {
+#line 3442
+ CError_FATAL();
+ }
+
+ if (dest->arg == RegClass_SPR) {
+ int i;
+ dest->kind = PCOp_SYSREG;
+ for (i = 0; i < 4; i++) {
+ if (dest->data.reg.reg == spr_to_sysreg[i]) {
+ dest->kind = PCOp_REGISTER;
+ dest->arg = RegClass_SPR;
+ dest->data.reg.reg = i;
+ break;
+ }
+ }
+ pcsetsideeffects(pc);
+ } else if (dest->arg == RegClass_6 || dest->arg == RegClass_DCR) {
+ short save = dest->data.reg.reg;
+ dest->kind = PCOp_IMMEDIATE;
+ dest->data.imm.value = save;
+ dest->data.imm.obj = NULL;
+ break;
+ }
+
+ if ((src->u.reg.effect & EffectWrite) && dest->data.reg.reg < n_real_registers[dest->arg]) {
+ if (src->u.reg.object) {
+ if (Registers_GetVarInfo(src->u.reg.object)->flags & VarInfoFlag4) {
+ int reg, regHi;
+#line 3474
+ CError_ASSERT(dest->arg == RegClass_GPR);
+
+ regHi = OBJECT_REG_HI(src->u.reg.object);
+ reg = OBJECT_REG(src->u.reg.object);
+ retain_GPR_pair(src->u.reg.object, reg, regHi);
+ } else {
+ retain_register(src->u.reg.object, dest->arg, dest->data.reg.reg);
+ }
+ } else {
+ retain_register(NULL, dest->arg, dest->data.reg.reg);
+ }
+ }
+
+ break;
+ }
+
+ case IAOpnd_Lab:
+ if (!src->u.lab.label->pclabel)
+ src->u.lab.label->pclabel = makepclabel();
+ dest->kind = PCOp_LABEL;
+ dest->data.label.label = src->u.lab.label->pclabel;
+ break;
+
+ case IAOpnd_3:
+ case IAOpnd_4:
+ dest->kind = PCOp_MEMORY;
+ dest->arg = src->u.obj.unk;
+ dest->data.mem.obj = src->u.obj.obj;
+ dest->data.mem.offset = src->u.obj.offset;
+ if (pc->flags & (fPCodeFlag2 | fPCodeFlag4 | fPCodeFlag20000 | fPCodeFlag40000)) {
+ pc->_18 = make_alias(dest->data.mem.obj, dest->data.mem.offset, nbytes_loaded_or_stored_by(pc));
+ if (is_volatile_object(dest->data.mem.obj))
+ pc->flags |= fIsVolatile;
+ if (OBJ_GET_TARGET_CONST(dest->data.mem.obj))
+ pc->flags |= fIsConst;
+ }
+ break;
+
+ case IAOpnd_LabDiff:
+ if (src->u.labdiff.label1->pclabel == NULL)
+ src->u.labdiff.label1->pclabel = makepclabel();
+ if (src->u.labdiff.label2->pclabel == NULL)
+ src->u.labdiff.label2->pclabel = makepclabel();
+ if (pc->flags & (fPCodeFlag2 | fPCodeFlag4))
+ pc->flags |= fPCodeFlag20;
+ dest->kind = PCOp_LABELDIFF;
+ dest->data.labeldiff.labelA = src->u.labdiff.label1->pclabel;
+ dest->data.labeldiff.labelB = src->u.labdiff.label2->pclabel;
+ dest->arg = src->negated;
+ dest->data.labeldiff.offset = src->u.labdiff.offset;
+ break;
+
+ default:
+#line 3528
+ CError_FATAL();
+ }
+ }
+
+ index++;
+ dest++;
+ src++;
+ }
+
+ if (ia->opcode == PC_STMW || ia->opcode == PC_LMW) {
+ int i;
+ for (i = reg; i < 32; i++, dest++) {
+ dest->kind = PCOp_REGISTER;
+ dest->arg = RegClass_GPR;
+ dest->data.reg.reg = i;
+ dest->data.reg.effect = (short) ((ia->opcode == PC_LMW) ? EffectWrite : EffectRead);
+ }
+ }
+
+ if (ia->flags & IAFlag2) {
+ UInt32 masks[5] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
+ branch_record_volatiles(dest, masks);
+ if (copts.exceptions && current_statement && assembler_type == 0)
+ noteexceptionactionregisters(current_statement->dobjstack, dest);
+ }
+
+ return pc;
+}
+
+void InlineAsm_TranslateIRtoPCode(Statement *stmt) {
+ InlineAsm *ia;
+ PCode *pc;
+
+ ia = (InlineAsm *) stmt->expr;
+ pc = InlineAsm_TranslateIRtoPCodePPC(ia, opcodeinfo[ia->opcode].x8, assembler_type);
+ appendpcode(pclastblock, pc);
+
+ if ((ia->flags2 & IAFlagsB_40) || !copts.optimizewithasm)
+ setpcodeflags(fSideEffects);
+
+ if (ia->flags2 & IAFlagsB_1) {
+ if (PCODE_FLAG_SET_F(pc) & fPCodeFlag8000000)
+ pcsetrecordbit(pclastblock->lastPCode);
+ else
+ CError_Error(CErrorStr261);
+ }
+
+ if (ia->flags2 & IAFlagsB_2) {
+ if (PCODE_FLAG_SET_F(pc) & fPCodeFlag4000000)
+ setpcodeflags(fOverflow); // idk?
+ else
+ CError_Error(CErrorStr261);
+ }
+
+ if (ia->flags2 & IAFlagsB_4) {
+ if (PCODE_FLAG_SET_T(pc) & fPCodeFlag20000000) {
+ int i;
+ for (i = 0; i < pc->argCount; i++) {
+ if (pc->args[i].kind == PCOp_LABEL || pc->args[i].kind == PCOp_MEMORY) {
+ PPCError_Error(177);
+ break;
+ }
+ }
+ setpcodeflags(fAbsolute); // idk?
+ } else {
+ CError_Error(CErrorStr261);
+ }
+ }
+
+ if (ia->flags2 & IAFlagsB_8) {
+ if (PCODE_FLAG_SET_T(pc) & fPCodeFlag2000000) {
+ pcsetlinkbit(pclastblock->lastPCode);
+ if (!(ia->flags & IAFlag2)) {
+ pclastblock->lastPCode->flags &= ~fPCodeFlag8;
+ pclastblock->lastPCode->flags |= fPCodeFlag1;
+ }
+ makes_call = 1;
+ } else {
+ CError_Error(CErrorStr261);
+ }
+ }
+
+ if (ia->flags2 & IAFlagsB_10)
+ setpcodeflags(fPCodeFlag8000000);
+ if (ia->flags2 & IAFlagsB_20)
+ setpcodeflags(fPCodeFlag4000000);
+
+ if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 16) {
+ PCodeLabel *dest = NULL;
+ PCodeLabel *src = makepclabel();
+ switch (pc->op) {
+ case PC_BC:
+ if (pc->args[3].kind == PCOp_LABEL)
+ dest = pc->args[3].data.label.label;
+ break;
+ case PC_BT:
+ case PC_BF:
+ case PC_BDNZT:
+ case PC_BDNZF:
+ case PC_BDZT:
+ case PC_BDZF:
+ if (pc->args[2].kind == PCOp_LABEL)
+ dest = pc->args[2].data.label.label;
+ break;
+ case PC_BDNZ:
+ case PC_BDZ:
+ if (pc->args[0].kind == PCOp_LABEL)
+ dest = pc->args[0].data.label.label;
+ break;
+ default:
+#line 3715
+ CError_FATAL();
+ }
+
+ if (dest) {
+ pcbranch(pclastblock, dest);
+ pcbranch(pclastblock, src);
+ makepcblock();
+ pclabel(pclastblock, src);
+ }
+ return;
+ }
+
+ if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 18) {
+ PCodeLabel *label;
+ if (ia->flags2 & IAFlagsB_8) {
+ label = makepclabel();
+ pcbranch(pclastblock, label);
+ }
+ if (pc->args[0].kind == PCOp_LABEL)
+ pcbranch(pclastblock, pc->args[0].data.label.label);
+ makepcblock();
+ if (ia->flags2 & IAFlagsB_8) {
+ pclabel(pclastblock, label);
+ }
+ return;
+ }
+
+ if (OPCODE_PART_1(opcodeinfo[pc->op].insn) == 19) {
+ switch (pc->op) {
+ case PC_BLR:
+ case PC_RFI:
+ if (asm_alloc_flags[3])
+ asm_alloc_flags[9] = 1;
+ else
+ asm_alloc_flags[8] = 1;
+
+ if (asm_alloc_flags[4])
+ asm_alloc_flags[5] = 1;
+
+ if (pc->op == PC_BLR)
+ asm_alloc_flags[6] = 1;
+ else
+ asm_alloc_flags[7] = 1;
+ break;
+ }
+ }
+}
+
+const char *InlineAsm_GetMnemonic(InlineAsm *ia) {
+ return opcodeinfo[ia->opcode].name;
+}
+
+static void savepicbase(short reg, HashNameNode *name) {
+ IALookupResult result;
+
+ if (!InlineAsm_LookupSymbol(name, &result))
+ result.label = InlineAsm_DeclareLabel(name);
+
+ pic_base_label = result.label;
+ pic_base_reg = reg;
+ uses_globals = 1;
+}
+
+static SInt32 InlineAsm_OpcodeSize(InlineAsm *ia) {
+ if (opcodeinfo[ia->opcode].flags & (fPCodeFlag2 | fPCodeFlag4)) {
+ switch (ia->opcode) {
+ case PC_LBZ:
+ case PC_LBZU:
+ case PC_LBZX:
+ case PC_LBZUX:
+ case PC_STB:
+ case PC_STBU:
+ case PC_STBX:
+ case PC_STBUX:
+ return 1;
+ case PC_LHZ:
+ case PC_LHZU:
+ case PC_LHZX:
+ case PC_LHZUX:
+ case PC_LHA:
+ case PC_LHAU:
+ case PC_LHAX:
+ case PC_LHAUX:
+ case PC_LHBRX:
+ case PC_STH:
+ case PC_STHU:
+ case PC_STHX:
+ case PC_STHUX:
+ case PC_STHBRX:
+ return 2;
+ case PC_LWZ:
+ case PC_LWZU:
+ case PC_LWZX:
+ case PC_LWZUX:
+ case PC_LWBRX:
+ case PC_STW:
+ case PC_STWU:
+ case PC_STWX:
+ case PC_STWUX:
+ case PC_STWBRX:
+ case PC_LFS:
+ case PC_LFSU:
+ case PC_LFSX:
+ case PC_LFSUX:
+ case PC_STFS:
+ case PC_STFSU:
+ case PC_STFSX:
+ case PC_STFSUX:
+ case PC_LWARX:
+ case PC_STFIWX:
+ case PC_STWCX:
+ case PC_ECIWX:
+ case PC_ECOWX:
+ case PC_MFROM:
+ case PC_LSCBX:
+ return 4;
+ case PC_LMW:
+ case PC_STMW:
+ if (ia->args[0].type == IAOpnd_Reg && ia->args[0].u.reg.object == NULL)
+ return (32 - ia->args[0].u.reg.num) * 4;
+ else
+ return 128;
+ case PC_LFD:
+ case PC_LFDU:
+ case PC_LFDX:
+ case PC_LFDUX:
+ case PC_STFD:
+ case PC_STFDU:
+ case PC_STFDX:
+ case PC_STFDUX:
+ return 8;
+ case PC_LSWI:
+ case PC_STSWI:
+ return ia->args[2].u.imm.value;
+ case PC_LSWX:
+ case PC_STSWX:
+ return 128;
+ case PC_LVEBX:
+ case PC_STVEBX:
+ return 1;
+ case PC_LVEHX:
+ case PC_STVEHX:
+ return 2;
+ case PC_LVEWX:
+ case PC_STVEWX:
+ return 4;
+ case PC_LVSL:
+ case PC_LVSR:
+ case PC_LVX:
+ case PC_LVXL:
+ case PC_STVX:
+ case PC_STVXL:
+ return 16;
+ default:
+#line 3924
+ CError_FATAL();
+ }
+ } else {
+ if (opcodeinfo[ia->opcode].flags & fPCodeFlag80000000)
+ return 4;
+ if (opcodeinfo[ia->opcode].flags & fPCodeFlag40000000)
+ return 8;
+ if (opcodeinfo[ia->opcode].flags & (fPCodeFlag80000000 | fPCodeFlag40000000))
+ return 16;
+
+ if (opcodeinfo[ia->opcode].flags & fSideEffects) {
+ switch (ia->opcode) {
+ case PC_TLBIE:
+ case PC_TLBLD:
+ case PC_TLBLI:
+ return 4;
+ default:
+#line 3941
+ CError_FATAL();
+ }
+ }
+ }
+
+#line 3944
+ CError_FATAL();
+ return 0;
+}
+
+void CodeGen_GetAsmEffects(Statement *stmt, IAEffects *effects) {
+ InlineAsm *ia;
+ OpcodeInfo *info;
+ int i;
+ IAOperand *op;
+ VarInfo *vi;
+
+ ia = (InlineAsm *) stmt->expr;
+ info = &opcodeinfo[ia->opcode];
+
+ effects->numoperands = 0;
+ effects->numlabels = 0;
+ effects->x1 = 0;
+ effects->x2 = 0;
+ effects->x3 = 0;
+ effects->x4 = 0;
+ effects->x0 = 0;
+ effects->x5 = 0;
+
+ if (info->flags & fPCodeFlag20) {
+ if (info->flags & fPCodeFlag2)
+ effects->x1 = 1;
+ if (info->flags & fPCodeFlag4)
+ effects->x2 = 1;
+ }
+
+ if (PCODE_FLAG_SET_T(info) & fPCodeFlag2000000) {
+ if (ia->flags2 & IAFlagsB_8)
+ effects->x4 = 1;
+ else if ((info->flags & fPCodeFlag8) || (info->flags & fPCodeFlag4))
+ effects->x3 = 1;
+
+ if (ia->opcode == PC_B) {
+ if (ia->args[0].type == IAOpnd_Imm)
+ effects->x0 = 1;
+ effects->x5 = 1;
+ }
+ }
+
+ if (info->flags & fSideEffects)
+ effects->x0 = 1;
+
+ if (ia->opcode == PC_BC && (ia->flags2 & IAFlagsB_8))
+ effects->x4 = 1;
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ switch (op->type) {
+ case IAOpnd_0:
+ case IAOpnd_Imm:
+ break;
+ case IAOpnd_Reg:
+ if (op->u.reg.object) {
+ if ((vi = Registers_GetVarInfo(op->u.reg.object)))
+ vi->flags |= VarInfoFlag40;
+ if (op->u.reg.effect & EffectRead) {
+ if (
+ TYPE_FITS_IN_REGISTER(op->u.reg.object->type) ||
+ IS_TYPE_FLOAT(op->u.reg.object->type) ||
+ IS_TYPE_VECTOR(op->u.reg.object->type)
+ ) {
+ effects->operands[effects->numoperands].type = IAEffect_0;
+ effects->operands[effects->numoperands].object = op->u.reg.object;
+ effects->operands[effects->numoperands].offset = 0;
+ effects->operands[effects->numoperands].size = op->u.reg.object->type->size;
+ effects->numoperands++;
+ } else {
+#line 4051
+ CError_FATAL();
+ }
+ }
+ }
+ break;
+ case IAOpnd_3:
+ case IAOpnd_4:
+ if (op->u.obj.obj) {
+ if (info->flags & fPCodeFlag2) {
+ effects->operands[effects->numoperands].type = IAEffect_0;
+ effects->operands[effects->numoperands].object = op->u.obj.obj;
+ effects->operands[effects->numoperands].offset = op->u.obj.offset;
+ effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia);
+ effects->numoperands++;
+ } else if (!(info->flags & (fPCodeFlag1 | fPCodeFlag8))) {
+ effects->operands[effects->numoperands].type = IAEffect_3;
+ effects->operands[effects->numoperands].object = op->u.obj.obj;
+ effects->operands[effects->numoperands].offset = op->u.obj.offset;
+ effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia);
+ effects->numoperands++;
+ }
+ }
+ break;
+ case IAOpnd_Lab:
+ effects->labels[effects->numlabels] = op->u.lab.label;
+ effects->numlabels++;
+ break;
+ case IAOpnd_LabDiff:
+ effects->labels[effects->numlabels] = op->u.labdiff.label1;
+ effects->numlabels++;
+ effects->labels[effects->numlabels] = op->u.labdiff.label2;
+ effects->numlabels++;
+ effects->x3 = 1;
+ break;
+ default:
+#line 4087
+ CError_FATAL();
+ }
+
+#line 4090
+ CError_ASSERT(effects->numoperands <= 16);
+#line 4093
+ CError_ASSERT(effects->numlabels <= 16);
+ }
+
+ for (i = 0, op = ia->args; i < ia->argcount; i++, op++) {
+ switch (op->type) {
+ case IAOpnd_Reg:
+ if (op->u.reg.object) {
+ if ((vi = Registers_GetVarInfo(op->u.reg.object)))
+ vi->flags |= VarInfoFlag40;
+ if (op->u.reg.effect & EffectWrite) {
+ if (
+ TYPE_FITS_IN_REGISTER(op->u.reg.object->type) ||
+ IS_TYPE_FLOAT(op->u.reg.object->type) ||
+ IS_TYPE_VECTOR(op->u.reg.object->type)
+ ) {
+ effects->operands[effects->numoperands].type = IAEffect_1;
+ effects->operands[effects->numoperands].object = op->u.reg.object;
+ effects->operands[effects->numoperands].offset = 0;
+ effects->operands[effects->numoperands].size = op->u.reg.object->type->size;
+ effects->numoperands++;
+ } else {
+#line 4132
+ CError_FATAL();
+ }
+ }
+ }
+ break;
+ case IAOpnd_3:
+ case IAOpnd_4:
+ if (op->u.obj.obj) {
+ if (info->flags & fPCodeFlag4) {
+ effects->operands[effects->numoperands].type = IAEffect_1;
+ effects->operands[effects->numoperands].object = op->u.obj.obj;
+ effects->operands[effects->numoperands].offset = op->u.obj.offset;
+ effects->operands[effects->numoperands].size = InlineAsm_OpcodeSize(ia);
+ effects->numoperands++;
+ }
+ }
+ break;
+ }
+
+#line 4151
+ CError_ASSERT(effects->numoperands <= 16);
+ }
+
+ if ((info->flags & (fPCodeFlag1 | fPCodeFlag8)) && (SInt32)effects->numlabels == 0)
+ effects->x3 = 1;
+}
+
+void CodeGen_PropagateIntoAsm(Statement *stmt, Object *obj, ENode *expr) {
+ InlineAsm *ia;
+ Object *newobj;
+
+ ia = (InlineAsm *) stmt->expr;
+ if (ENODE_IS(expr, EOBJREF)) {
+ newobj = expr->data.objref;
+ if (obj->otype == newobj->otype && obj->datatype == newobj->datatype) {
+ int i;
+ for (i = 0; i < ia->argcount; i++) {
+ switch (ia->args[i].type) {
+ case IAOpnd_Reg:
+ if (ia->args[i].u.reg.object == obj &&
+ (ia->args[i].u.reg.effect & (EffectRead | EffectWrite)) == EffectRead) {
+ if (TYPE_FITS_IN_REGISTER(newobj->type) &&
+ ia->args[i].u.reg.rclass == RegClass_GPR) {
+ ia->args[i].u.reg.object = newobj;
+ } else if (IS_TYPE_FLOAT(newobj->type) &&
+ ia->args[i].u.reg.rclass == RegClass_FPR) {
+ ia->args[i].u.reg.object = newobj;
+ } else if (IS_TYPE_VECTOR(newobj->type) &&
+ ia->args[i].u.reg.rclass == RegClass_VR) {
+ ia->args[i].u.reg.object = newobj;
+ }
+ }
+ break;
+ case IAOpnd_3:
+ case IAOpnd_4:
+ if (!(opcodeinfo[ia->opcode].flags & (fPCodeFlag4 | fPCodeFlag40000)) &&
+ ia->args[i].u.obj.obj == obj)
+ ia->args[i].u.obj.obj = newobj;
+ break;
+ }
+ }
+ }
+ }
+}
+
+Statement *CodeGen_CopyAsmStat(Statement *stmt) {
+ Statement *copy;
+ SInt32 size;
+ InlineAsm *ia;
+ InlineAsm *iacopy;
+
+ copy = galloc(sizeof(Statement));
+ *copy = *stmt;
+
+ ia = (InlineAsm *) stmt->expr;
+ size = sizeof(InlineAsm) + sizeof(IAOperand) * ia->argcount;
+ iacopy = galloc(size);
+ memcpy(iacopy, ia, size);
+ copy->expr = (ENode *) iacopy;
+
+ return copy;
+}
+
diff --git a/compiler_and_linker/unsorted/InlineAsmRegisters.c b/compiler_and_linker/unsorted/InlineAsmRegisters.c
new file mode 100644
index 0000000..31f94c4
--- /dev/null
+++ b/compiler_and_linker/unsorted/InlineAsmRegisters.c
@@ -0,0 +1,50 @@
+#include "compiler/InlineAsmRegisters.h"
+#include "compiler/CompilerTools.h"
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct HashedRegister {
+ struct HashedRegister *next;
+ IARegister reg;
+} HashedRegister;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static HashedRegister *hashedregisters[64];
+
+void InlineAsm_InitializeRegisters() {
+ SInt32 i;
+
+ for (i = 0; i < 64; i++)
+ hashedregisters[i] = NULL;
+}
+
+void InlineAsm_InsertRegister(char *name, char rclass, short num, Object *object) {
+ HashedRegister **ptr;
+ HashedRegister *hr;
+
+ ptr = hashedregisters + (CHash(name) & 63);
+ hr = lalloc(sizeof(HashedRegister));
+ hr->reg.name = name;
+ hr->reg.rclass = rclass;
+ hr->reg.num = num;
+ hr->reg.object = object;
+
+ hr->next = *ptr;
+ *ptr = hr;
+}
+
+IARegister *InlineAsm_LookupRegister(char *name) {
+ HashedRegister *scan;
+ IARegister *reg;
+
+ for (scan = hashedregisters[CHash(name) & 63]; scan; scan = scan->next) {
+ reg = &scan->reg;
+ if (!strcmp(scan->reg.name, name))
+ return reg;
+ }
+
+ return NULL;
+}
diff --git a/compiler_and_linker/unsorted/InlineAsmRegistersPPC.c b/compiler_and_linker/unsorted/InlineAsmRegistersPPC.c
new file mode 100644
index 0000000..a60bc15
--- /dev/null
+++ b/compiler_and_linker/unsorted/InlineAsmRegistersPPC.c
@@ -0,0 +1,854 @@
+#include "compiler/InlineAsmRegistersPPC.h"
+#include "compiler/InlineAsm.h"
+#include "compiler/InlineAsmRegisters.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+#include "compiler/InlineAsmPPC.h"
+#include "compiler/CParser.h"
+#include "compiler/PPCError.h"
+#include "compiler/CFunc.h"
+
+#pragma pool_strings on
+
+#ifdef __MWERKS__
+#pragma options align=mac68k
+#endif
+typedef struct RegInfo {
+ struct RegInfo *next;
+ UInt32 b;
+ IARegister reg;
+} RegInfo;
+
+typedef struct AsmRegister {
+ char *name;
+ char rclass;
+ SInt32 num;
+} AsmRegister;
+
+typedef struct AsmSpr {
+ char *name;
+ SInt32 num;
+ UInt32 mask;
+} AsmSpr;
+#ifdef __MWERKS__
+#pragma options align=reset
+#endif
+
+static RegInfo *hashedsprs[64];
+static RegInfo *hasheddcrs[64];
+
+static AsmRegister asm_registers[] = {
+ "r0", RegClass_GPR, 0,
+ "r1", RegClass_GPR, 1,
+ "r2", RegClass_GPR, 2,
+ "r3", RegClass_GPR, 3,
+ "r4", RegClass_GPR, 4,
+ "r5", RegClass_GPR, 5,
+ "r6", RegClass_GPR, 6,
+ "r7", RegClass_GPR, 7,
+ "r8", RegClass_GPR, 8,
+ "r9", RegClass_GPR, 9,
+ "r10", RegClass_GPR, 10,
+ "r11", RegClass_GPR, 11,
+ "r12", RegClass_GPR, 12,
+ "r13", RegClass_GPR, 13,
+ "r14", RegClass_GPR, 14,
+ "r15", RegClass_GPR, 15,
+ "r16", RegClass_GPR, 16,
+ "r17", RegClass_GPR, 17,
+ "r18", RegClass_GPR, 18,
+ "r19", RegClass_GPR, 19,
+ "r20", RegClass_GPR, 20,
+ "r21", RegClass_GPR, 21,
+ "r22", RegClass_GPR, 22,
+ "r23", RegClass_GPR, 23,
+ "r24", RegClass_GPR, 24,
+ "r25", RegClass_GPR, 25,
+ "r26", RegClass_GPR, 26,
+ "r27", RegClass_GPR, 27,
+ "r28", RegClass_GPR, 28,
+ "r29", RegClass_GPR, 29,
+ "r30", RegClass_GPR, 30,
+ "r31", RegClass_GPR, 31,
+ "gpr0", RegClass_GPR, 0,
+ "gpr1", RegClass_GPR, 1,
+ "gpr2", RegClass_GPR, 2,
+ "gpr3", RegClass_GPR, 3,
+ "gpr4", RegClass_GPR, 4,
+ "gpr5", RegClass_GPR, 5,
+ "gpr6", RegClass_GPR, 6,
+ "gpr7", RegClass_GPR, 7,
+ "gpr8", RegClass_GPR, 8,
+ "gpr9", RegClass_GPR, 9,
+ "gpr10", RegClass_GPR, 10,
+ "gpr11", RegClass_GPR, 11,
+ "gpr12", RegClass_GPR, 12,
+ "gpr13", RegClass_GPR, 13,
+ "gpr14", RegClass_GPR, 14,
+ "gpr15", RegClass_GPR, 15,
+ "gpr16", RegClass_GPR, 16,
+ "gpr17", RegClass_GPR, 17,
+ "gpr18", RegClass_GPR, 18,
+ "gpr19", RegClass_GPR, 19,
+ "gpr20", RegClass_GPR, 20,
+ "gpr21", RegClass_GPR, 21,
+ "gpr22", RegClass_GPR, 22,
+ "gpr23", RegClass_GPR, 23,
+ "gpr24", RegClass_GPR, 24,
+ "gpr25", RegClass_GPR, 25,
+ "gpr26", RegClass_GPR, 26,
+ "gpr27", RegClass_GPR, 27,
+ "gpr28", RegClass_GPR, 28,
+ "gpr29", RegClass_GPR, 29,
+ "gpr30", RegClass_GPR, 30,
+ "gpr31", RegClass_GPR, 31,
+ "rtoc", RegClass_GPR, 2,
+ "RTOC", RegClass_GPR, 2,
+ "sp", RegClass_GPR, 1,
+ "SP", RegClass_GPR, 1,
+ "rsp", RegClass_GPR, 1,
+ "RSP", RegClass_GPR, 1,
+ "RPIC", RegClass_GPR, -2,
+ "rpic", RegClass_GPR, -2,
+ "f0", RegClass_FPR, 0,
+ "f1", RegClass_FPR, 1,
+ "f2", RegClass_FPR, 2,
+ "f3", RegClass_FPR, 3,
+ "f4", RegClass_FPR, 4,
+ "f5", RegClass_FPR, 5,
+ "f6", RegClass_FPR, 6,
+ "f7", RegClass_FPR, 7,
+ "f8", RegClass_FPR, 8,
+ "f9", RegClass_FPR, 9,
+ "f10", RegClass_FPR, 10,
+ "f11", RegClass_FPR, 11,
+ "f12", RegClass_FPR, 12,
+ "f13", RegClass_FPR, 13,
+ "f14", RegClass_FPR, 14,
+ "f15", RegClass_FPR, 15,
+ "f16", RegClass_FPR, 16,
+ "f17", RegClass_FPR, 17,
+ "f18", RegClass_FPR, 18,
+ "f19", RegClass_FPR, 19,
+ "f20", RegClass_FPR, 20,
+ "f21", RegClass_FPR, 21,
+ "f22", RegClass_FPR, 22,
+ "f23", RegClass_FPR, 23,
+ "f24", RegClass_FPR, 24,
+ "f25", RegClass_FPR, 25,
+ "f26", RegClass_FPR, 26,
+ "f27", RegClass_FPR, 27,
+ "f28", RegClass_FPR, 28,
+ "f29", RegClass_FPR, 29,
+ "f30", RegClass_FPR, 30,
+ "f31", RegClass_FPR, 31,
+ "fp0", RegClass_FPR, 0,
+ "fp1", RegClass_FPR, 1,
+ "fp2", RegClass_FPR, 2,
+ "fp3", RegClass_FPR, 3,
+ "fp4", RegClass_FPR, 4,
+ "fp5", RegClass_FPR, 5,
+ "fp6", RegClass_FPR, 6,
+ "fp7", RegClass_FPR, 7,
+ "fp8", RegClass_FPR, 8,
+ "fp9", RegClass_FPR, 9,
+ "fp10", RegClass_FPR, 10,
+ "fp11", RegClass_FPR, 11,
+ "fp12", RegClass_FPR, 12,
+ "fp13", RegClass_FPR, 13,
+ "fp14", RegClass_FPR, 14,
+ "fp15", RegClass_FPR, 15,
+ "fp16", RegClass_FPR, 16,
+ "fp17", RegClass_FPR, 17,
+ "fp18", RegClass_FPR, 18,
+ "fp19", RegClass_FPR, 19,
+ "fp20", RegClass_FPR, 20,
+ "fp21", RegClass_FPR, 21,
+ "fp22", RegClass_FPR, 22,
+ "fp23", RegClass_FPR, 23,
+ "fp24", RegClass_FPR, 24,
+ "fp25", RegClass_FPR, 25,
+ "fp26", RegClass_FPR, 26,
+ "fp27", RegClass_FPR, 27,
+ "fp28", RegClass_FPR, 28,
+ "fp29", RegClass_FPR, 29,
+ "fp30", RegClass_FPR, 30,
+ "fp31", RegClass_FPR, 31,
+ "v0", RegClass_VR, 0,
+ "v1", RegClass_VR, 1,
+ "v2", RegClass_VR, 2,
+ "v3", RegClass_VR, 3,
+ "v4", RegClass_VR, 4,
+ "v5", RegClass_VR, 5,
+ "v6", RegClass_VR, 6,
+ "v7", RegClass_VR, 7,
+ "v8", RegClass_VR, 8,
+ "v9", RegClass_VR, 9,
+ "v10", RegClass_VR, 10,
+ "v11", RegClass_VR, 11,
+ "v12", RegClass_VR, 12,
+ "v13", RegClass_VR, 13,
+ "v14", RegClass_VR, 14,
+ "v15", RegClass_VR, 15,
+ "v16", RegClass_VR, 16,
+ "v17", RegClass_VR, 17,
+ "v18", RegClass_VR, 18,
+ "v19", RegClass_VR, 19,
+ "v20", RegClass_VR, 20,
+ "v21", RegClass_VR, 21,
+ "v22", RegClass_VR, 22,
+ "v23", RegClass_VR, 23,
+ "v24", RegClass_VR, 24,
+ "v25", RegClass_VR, 25,
+ "v26", RegClass_VR, 26,
+ "v27", RegClass_VR, 27,
+ "v28", RegClass_VR, 28,
+ "v29", RegClass_VR, 29,
+ "v30", RegClass_VR, 30,
+ "v31", RegClass_VR, 31,
+ "vr0", RegClass_VR, 0,
+ "vr1", RegClass_VR, 1,
+ "vr2", RegClass_VR, 2,
+ "vr3", RegClass_VR, 3,
+ "vr4", RegClass_VR, 4,
+ "vr5", RegClass_VR, 5,
+ "vr6", RegClass_VR, 6,
+ "vr7", RegClass_VR, 7,
+ "vr8", RegClass_VR, 8,
+ "vr9", RegClass_VR, 9,
+ "vr10", RegClass_VR, 10,
+ "vr11", RegClass_VR, 11,
+ "vr12", RegClass_VR, 12,
+ "vr13", RegClass_VR, 13,
+ "vr14", RegClass_VR, 14,
+ "vr15", RegClass_VR, 15,
+ "vr16", RegClass_VR, 16,
+ "vr17", RegClass_VR, 17,
+ "vr18", RegClass_VR, 18,
+ "vr19", RegClass_VR, 19,
+ "vr20", RegClass_VR, 20,
+ "vr21", RegClass_VR, 21,
+ "vr22", RegClass_VR, 22,
+ "vr23", RegClass_VR, 23,
+ "vr24", RegClass_VR, 24,
+ "vr25", RegClass_VR, 25,
+ "vr26", RegClass_VR, 26,
+ "vr27", RegClass_VR, 27,
+ "vr28", RegClass_VR, 28,
+ "vr29", RegClass_VR, 29,
+ "vr30", RegClass_VR, 30,
+ "vr31", RegClass_VR, 31,
+ "cr0", RegClass_CRFIELD, 0,
+ "cr1", RegClass_CRFIELD, 1,
+ "cr2", RegClass_CRFIELD, 2,
+ "cr3", RegClass_CRFIELD, 3,
+ "cr4", RegClass_CRFIELD, 4,
+ "cr5", RegClass_CRFIELD, 5,
+ "cr6", RegClass_CRFIELD, 6,
+ "cr7", RegClass_CRFIELD, 7,
+ "crf0", RegClass_CRFIELD, 0,
+ "crf1", RegClass_CRFIELD, 1,
+ "crf2", RegClass_CRFIELD, 2,
+ "crf3", RegClass_CRFIELD, 3,
+ "crf4", RegClass_CRFIELD, 4,
+ "crf5", RegClass_CRFIELD, 5,
+ "crf6", RegClass_CRFIELD, 6,
+ "crf7", RegClass_CRFIELD, 7,
+ "lt", RegClass_6, 0,
+ "gt", RegClass_6, 1,
+ "eq", RegClass_6, 2,
+ "so", RegClass_6, 3,
+ "un", RegClass_6, 3,
+ "LT", RegClass_6, 0,
+ "GT", RegClass_6, 1,
+ "EQ", RegClass_6, 2,
+ "SO", RegClass_6, 3,
+ "UN", RegClass_6, 3,
+ NULL, 0, 0
+};
+
+static AsmSpr asm_sprs[] = {
+ "xer", 1, 0xFFFFF,
+ "lr", 8, 0xFFFFF,
+ "ctr", 9, 0xFFFFF,
+ "mq", 0, 1,
+ "rtcu", 4, 1,
+ "rtcl", 5, 1,
+ "dsisr", 0x12, 0xFF83F,
+ "dar", 0x13, 0xFF83F,
+ "dec", 0x16, 0xFF83F,
+ "sdr1", 0x19, 0xFE00F,
+ "srr0", 0x1A, 0xFFFFF,
+ "srr1", 0x1B, 0xFFFFF,
+ "eie", 0x50, 0x1830,
+ "eid", 0x51, 0x1830,
+ "nri", 0x52, 0x1830,
+ "cmpa", 0x90, 0x1830,
+ "cmpb", 0x91, 0x1830,
+ "cmpc", 0x92, 0x1830,
+ "cmpd", 0x93, 0x1830,
+ "icr", 0x94, 0x30,
+ "ecr", 0x94, 0x1800,
+ "der", 0x95, 0x1830,
+ "counta", 0x96, 0x1830,
+ "countb", 0x97, 0x1830,
+ "cmpe", 0x98, 0x1830,
+ "cmpf", 0x99, 0x1830,
+ "cmpg", 0x9A, 0x1830,
+ "cmph", 0x9B, 0x1830,
+ "lctrl1", 0x9C, 0x1830,
+ "lctrl2", 0x9D, 0x1830,
+ "ictrl", 0x9E, 0x1830,
+ "bar", 0x9F, 0x1830,
+ "vrsave", 0x100, 0x40000000,
+ "sprg0", 0x110, 0xFFFFF,
+ "sprg1", 0x111, 0xFFFFF,
+ "sprg2", 0x112, 0xFFFFF,
+ "sprg3", 0x113, 0xFFFFF,
+ "ear", 0x11A, 0xFE7CF,
+ "tbl", 0x11C, 0xFF83F,
+ "tbu", 0x11D, 0xFF83F,
+ "tbl_write", 0x11C, 0xFF83F,
+ "tbu_write", 0x11D, 0xFF83F,
+ "pvr", 0x11F, 0xFFFFF,
+ "ibat0u", 0x210, 0xFE7CF,
+ "mi_gra", 0x210, 0x1000,
+ "ibat0l", 0x211, 0xFE7CF,
+ "ibat1u", 0x212, 0xFE7CF,
+ "ibat1l", 0x213, 0xFE7CF,
+ "ibat2u", 0x214, 0xFE7CF,
+ "ibat2l", 0x215, 0xFE7CF,
+ "ibat3u", 0x216, 0xFE7CF,
+ "ibat3l", 0x217, 0xFE7CF,
+ "dbat0u", 0x218, 0xFE7CE,
+ "l2u_gra", 0x218, 0x1000,
+ "dbat0l", 0x219, 0xFE7CE,
+ "dbat1u", 0x21A, 0xFE7CE,
+ "dbat1l", 0x21B, 0xFE7CE,
+ "dbat2u", 0x21C, 0xFE7CE,
+ "dbat2l", 0x21D, 0xFE7CE,
+ "dbat3u", 0x21E, 0xFE7CE,
+ "dbat3l", 0x21F, 0xFE7CE,
+ "ic_cst", 0x230, 0x30,
+ "iccst", 0x230, 0x800,
+ "bbcmcr", 0x230, 0x1000,
+ "ic_adr", 0x231, 0x30,
+ "icadr", 0x231, 0x800,
+ "ic_dat", 0x232, 0x30,
+ "icdat", 0x232, 0x800,
+ "dc_cst", 0x238, 0x30,
+ "l2u_mcr", 0x238, 0x1000,
+ "dc_adr", 0x239, 0x30,
+ "dc_dat", 0x23A, 0x30,
+ "dpdr", 0x276, 0x1830,
+ "dpir", 0x277, 0x30,
+ "immr", 0x27E, 0x30,
+ "mi_ctr", 0x310, 0x30,
+ "mi_rba0", 0x310, 0x1000,
+ "mi_rba1", 0x311, 0x1000,
+ "mi_rba2", 0x312, 0x1000,
+ "mi_ap", 0x312, 0x30,
+ "mi_epn", 0x313, 0x30,
+ "mi_rba3", 0x313, 0x1000,
+ "mi_twc", 0x315, 0x30,
+ "mi_l1dl2p", 0x315, 0x30,
+ "mi_rpn", 0x316, 0x30,
+ "md_ctr", 0x318, 0x30,
+ "l2u_rba0", 0x318, 0x1000,
+ "l2u_rba1", 0x319, 0x1000,
+ "m_casid", 0x319, 0x30,
+ "md_ap", 0x31A, 0x30,
+ "l2u_rba2", 0x31A, 0x1000,
+ "l2u_rba3", 0x31B, 0x1000,
+ "md_epn", 0x31B, 0x30,
+ "m_twb", 0x31C, 0x30,
+ "md_l1p", 0x31C, 0x30,
+ "md_twc", 0x31D, 0x30,
+ "md_l1dl2p", 0x31D, 0x30,
+ "md_rpn", 0x31E, 0x30,
+ "m_tw", 0x31F, 0x30,
+ "m_save", 0x31F, 0x30,
+ "mi_dbcam", 0x330, 0x10,
+ "mi_cam", 0x330, 0x20,
+ "mi_ra0", 0x330, 0x1000,
+ "mi_ra1", 0x331, 0x1000,
+ "mi_dbram0", 0x331, 0x10,
+ "mi_ram0", 0x331, 0x20,
+ "mi_dbram1", 0x332, 0x10,
+ "mi_ram1", 0x332, 0x20,
+ "mi_ra2", 0x332, 0x1000,
+ "mi_ra3", 0x333, 0x1000,
+ "md_dbcam", 0x338, 0x10,
+ "md_cam", 0x338, 0x20,
+ "l2u_ra0", 0x338, 0x1000,
+ "l2u_ra1", 0x339, 0x1000,
+ "md_dbram0", 0x339, 0x10,
+ "md_ram0", 0x339, 0x20,
+ "md_dbram1", 0x33A, 0x10,
+ "md_ram1", 0x33A, 0x20,
+ "l2u_ra2", 0x33A, 0x1000,
+ "l2u_ra3", 0x33B, 0x1000,
+ "ummcr2", 0x3A0, 0x4000,
+ "ubamr", 0x3A7, 0x4000,
+ "ummcr0", 0x3A8, 0xE000,
+ "upmc1", 0x3A9, 0xE000,
+ "upmc2", 0x3AA, 0xE000,
+ "usia", 0x3AB, 0x2000,
+ "usiar", 0x3AB, 0x4000,
+ "ummcr1", 0x3AC, 0xE000,
+ "upmc3", 0x3AD, 0xE000,
+ "upmc4", 0x3AE, 0xE000,
+ "zpr", 0x3B0, 0x200,
+ "mmcr2", 0x3B0, 0x4000,
+ "pid", 0x3B1, 0x200,
+ "bamr", 0x3B7, 0x4000,
+ "mmcr0", 0x3B8, 0xE008,
+ "pmc1", 0x3B9, 0xE008,
+ "sgr", 0x3B9, 0x240,
+ "pmc2", 0x3BA, 0xE008,
+ "dcwr", 0x3BA, 0x240,
+ "sia", 0x3BB, 0xE008,
+ "siar", 0x3BB, 0x4000,
+ "sler", 0x3BB, 0x40,
+ "mmcr1", 0x3BC, 0xE000,
+ "pmc3", 0x3BD, 0xE000,
+ "pmc4", 0x3BE, 0xE000,
+ "sda", 0x3BF, 8,
+ "tbhu", 0x3CC, 0x240,
+ "tblu", 0x3CD, 0x240,
+ "dmiss", 0x3D0, 0x10006,
+ "dcmp", 0x3D1, 0x10006,
+ "hash1", 0x3D2, 0x10006,
+ "hash2", 0x3D3, 0x10006,
+ "icdbdr", 0x3D3, 0x7C0,
+ "imiss", 0x3D4, 0x10006,
+ "esr", 0x3D4, 0x7C0,
+ "icmp", 0x3D5, 0x10006,
+ "dear", 0x3D5, 0x7C0,
+ "rpa", 0x3D6, 0x10006,
+ "evpr", 0x3D6, 0x7C0,
+ "cdbcr", 0x3D7, 0x7C0,
+ "tsr", 0x3D8, 0x7C0,
+ "tcr", 0x3D8, 2,
+ "tcr", 0x3DA, 0x7C0,
+ "ibr", 0x3DA, 2,
+ "pit", 0x3DB, 0x7C0,
+ "esasrr", 0x3DB, 2,
+ "tbhi", 0x3DC, 0x7C0,
+ "tblo", 0x3DD, 0x7C0,
+ "srr2", 0x3DE, 0x7C0,
+ "sebr", 0x3DE, 2,
+ "srr3", 0x3DF, 0x7C0,
+ "ser", 0x3DF, 2,
+ "mid0", 0x3F0, 0x1E00F,
+ "dbsr", 0x3F0, 0x80,
+ "hid1", 0x3F1, 0x1E007,
+ "hid2", 0x3F2, 1,
+ "iabr", 0x3F2, 0x1E00F,
+ "dbcr", 0x3F2, 0x7C0,
+ "hid2", 0x3F3, 0x10000,
+ "iac1", 0x3F4, 0x80,
+ "iac", 0x3F4, 0x40,
+ "dabr", 0x3F5, 0xE009,
+ "iac2", 0x3F5, 0x80,
+ "hid5", 0x3F5, 1,
+ "dac1", 0x3F6, 0x80,
+ "dac", 0x3F6, 0x40,
+ "msscr0", 0x3F6, 0x4000,
+ "dac2", 0x3F7, 0x80,
+ "l2cr", 0x3F9, 0xE000,
+ "dccr", 0x3FA, 0x7C0,
+ "iccr", 0x3FB, 0x7C0,
+ "ictc", 0x3FB, 0xE000,
+ "pbl1", 0x3FC, 0x80,
+ "thrm1", 0x3FC, 0xE000,
+ "pbu1", 0x3FD, 0x80,
+ "thrm2", 0x3FD, 0xE000,
+ "fpecr", 0x3FE, 0x1800,
+ "pbl2", 0x3FE, 0x80,
+ "thrm3", 0x3FE, 0xE000,
+ "pir", 0x3FF, 0x4008,
+ "hid15", 0x3FF, 1,
+ "pbu2", 0x3FF, 0x80,
+ NULL, 0, 0
+};
+
+UInt32 spr_cpus[1024] = {
+ 1, 0xFFFFF, 0, 0, 1, 1, 0, 0,
+ 0xFFFFF, 0xFFFFF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xFF83F, 0xFF83F, 0, 0, 0xFF83F, 0,
+ 0, 0xFE00F, 0xFFFFF, 0xFFFFF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1830, 0x1830, 0x1830, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830,
+ 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830, 0x1830,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x40000000, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF, 0, 0, 0, 0,
+ 0, 0, 0xFE7CF, 0, 0xFF83F, 0xFF83F, 0, 0xFFFFF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFF7CF, 0xFE7CF, 0xFE7CF, 0xFE7CF, 0xFE7CF, 0xFE7CF, 0xFE7CF, 0xFE7CF,
+ 0xFF7CE, 0xFE7CE, 0xFE7CE, 0xFE7CE, 0xFE7CE, 0xFE7CE, 0xFE7CE, 0xFE7CE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1830, 0x1830, 0x1830, 0, 0, 0, 0, 0,
+ 0x1030, 0x30, 0x30, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0x1830, 0x30,
+ 0, 0, 0, 0, 0, 0, 0x30, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1030, 0x1000, 0x1030, 0x1030, 0, 0x30, 0x30, 0,
+ 0x1030, 0x1030, 0x1030, 0x1030, 0x30, 0x30, 0x30, 0x30,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1030, 0x1030, 0x1030, 0x1000, 0, 0, 0, 0,
+ 0x1030, 0x1030, 0x1030, 0x1000, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x20000000, 0x20000000, 0x20000000, 0x20000000, 0x20000000, 0x20000000, 0x20000000, 0x20000000,
+ 0x20000000, 0x20000000, 0x20000000, 0x20000000, 0, 0, 0, 0,
+ 0x4000, 0, 0, 0, 0, 0, 0, 0x4000,
+ 0xE000, 0xE000, 0xE000, 0xE000, 0xE000, 0xE000, 0xE000, 0,
+ 0x4200, 0x200, 0, 0, 0, 0, 0, 0x4000,
+ 0xE008, 0xE248, 0xE248, 0xE048, 0xE000, 0xE000, 0xE000, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0x240, 0x240, 0, 0,
+ 0x10006, 0x10006, 0x10006, 0x107C6, 0x107C6, 0x107C6, 0x107C6, 0x7C0,
+ 0x7C2, 0, 0x7C2, 0x7C2, 0x7C0, 0x7C0, 0x7C2, 0x7C2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x1E08F, 0x1E007, 0x1E7CF, 0x10000, 0xC0, 0xE089, 0x40C0, 0x80,
+ 0, 0xE000, 0x7C0, 0xE7C0, 0xE080, 0xE080, 0xF880, 0xE089
+};
+
+static void InlineAsm_InsertSPR(char *name, short num, UInt32 b) {
+ RegInfo **ptr;
+ RegInfo *info;
+
+ ptr = hashedsprs + (CHash(name) & 63);
+ info = lalloc(sizeof(RegInfo));
+ info->b = b;
+ info->reg.name = name;
+ info->reg.rclass = RegClass_SPR;
+ info->reg.num = num;
+ info->reg.object = NULL;
+
+ info->next = *ptr;
+ *ptr = info;
+}
+
+static void InlineAsm_InsertRegisterDCR(char *name, UInt32 b, short num) {
+ RegInfo **ptr;
+ RegInfo *info;
+
+ ptr = hasheddcrs + (CHash(name) & 63);
+ info = lalloc(sizeof(RegInfo));
+ info->b = b;
+ info->reg.name = name;
+ info->reg.rclass = RegClass_DCR;
+ info->reg.num = num;
+ info->reg.object = NULL;
+
+ info->next = *ptr;
+ *ptr = info;
+}
+
+IARegister *InlineAsm_LookupRegisterPPCName(HashNameNode *name) {
+ IALookupResult result;
+ IARegister *reg;
+ Type *type;
+
+ if (InlineAsm_LookupSymbol(name, &result) && result.object && is_register_object(result.object)) {
+ type = result.object->type;
+ if ((reg = InlineAsm_LookupRegisterPPC(name->name)) && reg->object == result.object)
+ return reg;
+
+ if (IS_TYPE_FLOAT(type)) {
+ InlineAsm_InsertRegister(name->name, RegClass_FPR, 0, result.object);
+ } else if (IS_TYPE_VECTOR(type)) {
+ InlineAsm_InsertRegister(name->name, RegClass_VR, 0, result.object);
+ } else {
+ InlineAsm_InsertRegister(name->name, RegClass_GPR, 0, result.object);
+ }
+ }
+
+ return InlineAsm_LookupRegisterPPC(name->name);
+}
+
+IARegister *InlineAsm_LookupRegisterPPC(char *name) {
+ RegInfo *scan;
+ IARegister *reg;
+ IARegister *check;
+ char buf[40];
+
+ if ((check = InlineAsm_LookupRegister(name)))
+ return check;
+
+ reg = NULL;
+ if (strlen(name) < 40)
+ CToLowercase(name, buf);
+ else
+ return NULL;
+
+ for (scan = hashedsprs[CHash(buf) & 63]; scan; scan = scan->next) {
+ check = &scan->reg;
+ if (!strcmp(scan->reg.name, buf)) {
+ if (cpu == CPUMask_Generic) {
+ if ((cpu & CPUFLAG_LOW_MASK) == ((cpu & CPUFLAG_LOW_MASK) & scan->b))
+ return check;
+ } else {
+ if (scan->b & cpu)
+ return check;
+ }
+ reg = check;
+ }
+ }
+
+ if (reg) {
+ if (copts.warn_possunwant)
+ PPCError_Warning(117, name);
+ return reg;
+ }
+
+ if (!strncmp("spr", buf, 3)) {
+ static IARegister thespr;
+ UInt32 result;
+ Boolean overflow;
+ ScanDec(buf + 3, &result, &overflow);
+ if (overflow || result > 1024) {
+ PPCError_Error(117, name);
+ return NULL;
+ }
+
+ thespr.name = NULL;
+ thespr.rclass = RegClass_SPR;
+ thespr.num = result;
+ thespr.object = NULL;
+
+ if (copts.warn_possunwant) {
+ if (cpu == CPUMask_Generic) {
+ if ((cpu & CPUFLAG_LOW_MASK) != ((cpu & CPUFLAG_LOW_MASK) & spr_cpus[result]))
+ PPCError_Warning(117, name);
+ } else {
+ if (!(cpu & spr_cpus[result]))
+ PPCError_Warning(117, name);
+ }
+ }
+
+ return &thespr;
+ }
+
+ return NULL;
+}
+
+IARegister *InlineAsm_LookupDCRRegister(char *name) {
+ RegInfo *scan;
+ IARegister *check;
+ IARegister *reg;
+ char buf[40];
+
+ if (strlen(name) < 40)
+ CToLowercase(name, buf);
+ else
+ return NULL;
+
+ reg = NULL;
+ for (scan = hasheddcrs[CHash(buf) & 63]; scan; scan = scan->next) {
+ check = &scan->reg;
+ if (!strcmp(scan->reg.name, buf)) {
+ if (cpu == CPUMask_Generic) {
+ if ((cpu & CPUFLAG_LOW_MASK) == ((cpu & CPUFLAG_LOW_MASK) & scan->b))
+ return check;
+ } else {
+ if (scan->b & cpu)
+ return check;
+ }
+ reg = check;
+ }
+ }
+
+ if (reg) {
+ if (copts.warn_possunwant)
+ PPCError_Warning(117, name);
+ return reg;
+ }
+
+ if (!strncmp("dcr", buf, 3)) {
+ static IARegister thespr;
+ UInt32 result;
+ Boolean overflow;
+ ScanDec(buf + 3, &result, &overflow);
+ if (overflow || result > 1024) {
+ PPCError_Error(117, name);
+ return NULL;
+ }
+
+ thespr.name = NULL;
+ thespr.rclass = RegClass_DCR;
+ thespr.num = result;
+ thespr.object = NULL;
+ return &thespr;
+ }
+
+ return NULL;
+}
+
+void InlineAsm_InitializeRegistersPPC(void) {
+ AsmRegister *asmreg;
+ AsmSpr *asmspr;
+ HashNameNode *name;
+ Object *obj;
+ ObjectList *list;
+ char buf[16];
+ SInt32 i;
+
+ setup_diagnostic_reg_strings();
+
+ for (i = 0; i < 64; i++)
+ hashedsprs[i] = NULL;
+ for (i = 0; i < 64; i++)
+ hasheddcrs[i] = NULL;
+
+ for (asmreg = asm_registers; asmreg->name; asmreg++) {
+ name = GetHashNameNodeExport(asmreg->name);
+ for (list = arguments; list; list = list->next) {
+ obj = list->object;
+ if (obj && obj->name == name) {
+ switch (asmreg->rclass) {
+ case RegClass_SPR:
+ case RegClass_CRFIELD:
+ case RegClass_VR:
+ case RegClass_FPR:
+ case RegClass_GPR:
+ sprintf(buf, register_class_format[asmreg->rclass], asmreg->num);
+ break;
+ case RegClass_6:
+ sprintf(buf, "crbit_%ld", asmreg->num);
+ break;
+ case RegClass_DCR:
+ sprintf(buf, "DCR%ld", asmreg->num);
+ break;
+ default:
+ sprintf(buf, "{?}%ld", asmreg->num);
+ break;
+ }
+ PPCError_Warning(100, obj->name->name, buf);
+ }
+ }
+ for (list = locals; list; list = list->next) {
+ obj = list->object;
+ if (obj && obj->name == name) {
+ switch (asmreg->rclass) {
+ case RegClass_SPR:
+ case RegClass_CRFIELD:
+ case RegClass_VR:
+ case RegClass_FPR:
+ case RegClass_GPR:
+ sprintf(buf, register_class_format[asmreg->rclass], asmreg->num);
+ break;
+ case RegClass_6:
+ sprintf(buf, "crbit_%ld", asmreg->num);
+ break;
+ case RegClass_DCR:
+ sprintf(buf, "DCR%ld", asmreg->num);
+ break;
+ default:
+ sprintf(buf, "{?}%ld", asmreg->num);
+ break;
+ }
+ PPCError_Warning(100, obj->name->name, buf);
+ }
+ }
+
+ InlineAsm_InsertRegister(asmreg->name, asmreg->rclass, asmreg->num, NULL);
+ }
+
+ for (asmspr = asm_sprs; asmspr->name; asmspr++) {
+ InlineAsm_InsertSPR(asmspr->name, asmspr->num, asmspr->mask);
+ }
+}
diff --git a/compiler_and_linker/unsorted/InstrSelection.c b/compiler_and_linker/unsorted/InstrSelection.c
new file mode 100644
index 0000000..ac60baf
--- /dev/null
+++ b/compiler_and_linker/unsorted/InstrSelection.c
@@ -0,0 +1,4858 @@
+#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/Operands.h"
+#include "compiler/PCode.h"
+#include "compiler/PCodeInfo.h"
+#include "compiler/PCodeUtilities.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/TOC.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/enode.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
+
+// TODO: move me
+extern void move_block(Operand *, Operand *, SInt32, SInt32);
+
+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;
+#line 250
+ CError_ASSERT(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.value);
+
+ 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.value);
+
+ 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:
+#line 456
+ CError_FATAL();
+ }
+ 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)) {
+#line 681
+ CError_FATAL();
+ }
+}
+
+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.optimize_for_size && 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.optimize_for_size && 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.optimize_for_size && 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 {
+#line 1759
+ CError_FATAL();
+ }
+ 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:
+#line 1810
+ CError_FATAL();
+ }
+ 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 {
+#line 2224
+ CError_FATAL();
+ }
+}
+
+void gen_BITFIELD(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+#line 2238
+ CError_FATAL();
+}
+
+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) {
+#line 2294
+ CError_FATAL();
+}
+
+void gen_STRINGCONST(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+#line 2308
+ CError_FATAL();
+}
+
+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 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:
+#line 2780
+ CError_FATAL();
+ }
+
+ 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_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);
+ }
+ 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_reg = op.reg;
+ if (flag) {
+ fneg_reg = ALLOC_FPR();
+ emitpcode(PC_FNEG, fneg_reg, op.reg);
+ }
+
+ final_reg = outputReg ? outputReg : ALLOC_FPR();
+ emitpcode(PC_FSEL, final_reg, fneg_reg, op1.reg, op2.reg);
+ break;
+ default:
+#line 2862
+ CError_FATAL();
+ }
+
+ 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);
+ op2.optype = OpndType_GPR;
+ op2.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 {
+#line 3119
+ CError_FATAL();
+ }
+
+ 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:
+#line 3168
+ CError_FATAL();
+ }
+ }
+
+ 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));
+
+#line 3704
+ CError_ASSERT(ENODE_IS(expr1, EINDIRECT));
+ CError_ASSERT(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:
+#line 3744
+ CError_FATAL();
+ }
+
+ 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:
+#line 2862
+ CError_FATAL();
+ }
+
+ 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));
+#line 3966
+ CError_ASSERT(ENODE_IS(expr1, EINDIRECT));
+#line 3968
+ CError_ASSERT(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);
+#line 3979
+ CError_ASSERT(outputReg);
+
+ GEN_NODE(expr1, &op1);
+ op3 = op1;
+
+#line 3986
+ CError_ASSERT(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) {
+}
+
+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) {
+#line 4160
+ CError_FATAL();
+}
+
+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.optimize_for_size && 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();
+#line 4853
+ CError_ASSERT(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();
+#line 4883
+ CError_ASSERT(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:
+#line 5160
+ CError_FATAL();
+ }
+}
+
+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);
+#line 5190
+ CError_ASSERT(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:
+#line 5206
+ CError_FATAL();
+ }
+}
+
+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 op1;
+ int tmpReg;
+ int reg;
+ int a;
+ int b;
+
+ left = cond->data.diadic.left;
+ right = cond->data.diadic.right;
+ memclrw(&op1, sizeof(Operand));
+
+ if (!IS_TYPE_FLOAT(left->rtype)) {
+ Operand op2;
+ Operand op3;
+ Operand op4;
+ memclrw(&op2, sizeof(Operand));
+ memclrw(&op3, sizeof(Operand));
+ memclrw(&op4, sizeof(Operand));
+
+ if (right->hascall) {
+ GEN_NODE(right, &op3);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op3, right->rtype, 0);
+ ENSURE_GPR(&op3, right->rtype, 0);
+ }
+
+ GEN_NODE(left, &op2);
+ if (left->rtype->size < 4)
+ extend32(&op2, left->rtype, 0);
+ ENSURE_GPR(&op2, left->rtype, 0);
+ } else {
+ GEN_NODE(left, &op2);
+ ENSURE_GPR(&op2, left->rtype, 0);
+ if (left->rtype->size < 4)
+ extend32(&op2, left->rtype, 0);
+
+ GEN_NODE(right, &op3);
+ if (!IS_INT_CONST_ZERO(right)) {
+ if (right->rtype->size < 4)
+ extend32(&op3, right->rtype, 0);
+ ENSURE_GPR(&op3, right->rtype, 0);
+ }
+ }
+
+ switch (cond->type) {
+ case EEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0) {
+ PCode *pc = pclastblock->lastPCode;
+ if (pc->op == PC_RLWINM && pc->args[0].data.reg.reg == op2.reg) {
+ SInt32 r6 = pc->args[2].data.imm.value;
+ SInt32 r7 = pc->args[3].data.imm.value;
+ SInt32 r3 = right->data.intval.lo;
+ if (r7 == pc->args[4].data.imm.value) {
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ if (r3 != (r3 & 1)) {
+ emitpcode(PC_LI, reg, 0);
+ } else if (r3 == 0) {
+ int tmpreg = ALLOC_GPR();
+ emitpcode(
+ PC_RLWINM, tmpreg,
+ pc->args[1].data.reg.reg,
+ (r6 + r7 + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, reg, tmpreg, 1);
+ } else if (r3 == 1) {
+ emitpcode(
+ PC_RLWINM, reg,
+ pc->args[1].data.reg.reg,
+ (r6 + r7 + 1) & 31, 31, 31);
+ } else {
+#line 5434
+ CError_FATAL();
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ //int tmpReg = ALLOC_GPR(); // affected
+ int tmpReg;
+ int t = used_virtual_registers[RegClass_GPR];
+ used_virtual_registers[RegClass_GPR]++;
+ emitpcode(PC_CNTLZW, t, op2.reg, 0);
+ tmpReg = t;
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ } else {
+ int tmpReg, tmpReg2;
+ tmpReg = ALLOC_GPR(); // affected
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg2, 27, 5, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+
+ case ENOTEQU:
+ if (
+ copts.peephole &&
+ IS_INT_CONST(right) &&
+ pclastblock->pcodeCount > 0) {
+ PCode *pc = pclastblock->lastPCode;
+ if (pc->op == PC_RLWINM && pc->args[0].data.reg.reg == op2.reg) {
+ SInt32 r6 = pc->args[2].data.imm.value;
+ SInt32 r7 = pc->args[3].data.imm.value;
+ SInt32 r3 = right->data.intval.lo;
+ if (r7 == pc->args[4].data.imm.value) {
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ if (r3 != (r3 & 1)) {
+ emitpcode(PC_LI, reg, 1);
+ } else if (r3 == 0) {
+ emitpcode(
+ PC_RLWINM, reg,
+ pc->args[1].data.reg.reg,
+ (r6 + r7 + 1) & 31, 31, 31);
+ } else if (r3 == 1) {
+ int tmpreg = ALLOC_GPR(); // affected
+ emitpcode(
+ PC_RLWINM, tmpreg,
+ pc->args[1].data.reg.reg,
+ (r6 + r7 + 1) & 31, 31, 31);
+ emitpcode(PC_XORI, reg, tmpreg, 1);
+ } else {
+#line 5503
+ CError_FATAL();
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+ }
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ if (copts.optimize_for_size) {
+ int tmpReg;
+ tmpReg = ALLOC_GPR(); // affected
+ emitpcode(PC_ADDIC, tmpReg, op2.reg, -1);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, reg, tmpReg, op2.reg);
+ } else {
+ int tmpReg, tmpReg2;
+ // tmpReg, tmpReg2 swap
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg2, tmpReg, op2.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg2, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ } else {
+ if (copts.optimize_for_size) {
+ int tmpReg, tmpReg2;
+ // tmpReg, tmpReg2 swap
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ADDIC, tmpReg2, tmpReg, -1);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFE, reg, tmpReg2, tmpReg);
+ } else {
+ int tmpReg, tmpReg2, tmpReg3;
+ // tmpReg, tmpReg2 swap
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg2, op3.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_OR, tmpReg3, tmpReg, tmpReg2);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg3, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+
+ case EGREATEREQU:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ int tmpReg;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op2.reg, 1, 31, 31);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_XORI, reg, tmpReg, 1);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+ op4 = op3;
+ op3 = op2;
+ op2 = op4;
+ case ELESSEQU:
+ if (is_unsigned(left->rtype)) {
+ if (copts.optimize_for_size) {
+ int tmpReg, tmpReg2;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_LI, tmpReg, -1);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg2, op2.reg, op3.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_SUBFZE, reg, tmpReg);
+ } else {
+ int tmpReg, tmpReg2, tmpReg3, tmpReg4;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op2.reg, op3.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ORC, tmpReg2, op3.reg, op2.reg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg3, tmpReg, 31, 1, 31);
+ tmpReg4 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg4, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+
+ if (IS_INT_CONST_ZERO(right)) {
+ int tmpReg, tmpReg2;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_LI, tmpReg, 1);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, op2.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWNM, reg, tmpReg, tmpReg2, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ } else {
+ int tmpReg, tmpReg2, tmpReg3;
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, op3.reg, 31);
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_RLWINM, tmpReg, op2.reg, 1, 31, 31);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg3, op2.reg, op3.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_ADDE, reg, tmpReg2, tmpReg);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+
+ case EGREATER:
+ if (!is_unsigned(left->rtype) && IS_INT_CONST_ZERO(right)) {
+ int tmpReg, tmpReg2;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_NEG, tmpReg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_ANDC, tmpReg2, tmpReg, op2.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg2, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+
+ op4 = op3;
+ op3 = op2;
+ op2 = op4;
+ case ELESS:
+ if (is_unsigned(left->rtype)) {
+ if (left->rtype->size <= 2) {
+ int tmpReg;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg, op3.reg, op2.reg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ } else {
+ if (copts.optimize_for_size) {
+ int tmpReg, tmpReg2;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_SUBFC, tmpReg, op3.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SUBFE, tmpReg2, tmpReg, tmpReg);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_NEG, reg, tmpReg2);
+ } else {
+ int tmpReg, tmpReg2, tmpReg3;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XOR, tmpReg, op3.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_CNTLZW, tmpReg2, tmpReg);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_SLW, tmpReg3, op3.reg, tmpReg2);
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg3, 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+ return;
+ } else {
+ if (IS_INT_CONST_ZERO(right)) {
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, op2.reg, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ } else {
+ int tmpReg, tmpReg2, tmpReg3, tmpReg4;
+ tmpReg = ALLOC_GPR();
+ emitpcode(PC_XOR, tmpReg, op3.reg, op2.reg);
+ tmpReg2 = ALLOC_GPR();
+ emitpcode(PC_SRAWI, tmpReg2, tmpReg, 1);
+ tmpReg3 = ALLOC_GPR();
+ emitpcode(PC_AND, tmpReg3, tmpReg, op3.reg);
+ tmpReg4 = ALLOC_GPR();
+ emitpcode(PC_SUBF, tmpReg4, tmpReg3, tmpReg2);
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ emitpcode(PC_RLWINM, reg, tmpReg4, 1, 31, 31);
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+ return;
+ }
+ }
+
+ default:
+#line 5777
+ CError_FATAL();
+ }
+ }
+
+ gen_condition(cond, &op1);
+ emitpcode(PC_MFCR, tmpReg = used_virtual_registers[RegClass_GPR]++);
+ a = 0;
+ b = op1.reg * 4;
+ switch (op1.regOffset) {
+ case ENOTEQU:
+ a = 1;
+ case EEQU:
+ b += 2;
+ break;
+ case EGREATEREQU:
+ a = 1;
+ break;
+ case ELESSEQU:
+ a = 1;
+ case EGREATER:
+ b += 1;
+ break;
+ }
+
+ reg = outputReg ? outputReg : ALLOC_GPR();
+ if (a) {
+ emitpcode(PC_RLWINM, tmpReg, tmpReg, b + 1, 31, 31);
+ emitpcode(PC_XORI, reg, tmpReg, 1);
+ } else {
+ emitpcode(PC_RLWINM, reg, tmpReg, b + 1, 31, 31);
+ }
+ output->optype = OpndType_GPR;
+ output->reg = reg;
+}
+
+void gen_negated_condition_gpr(ENode *cond, Operand *output, short outputReg) {
+}
+
+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) {
+}
+
+void compare_immediate_long(short nt, ENode *left, SInt32 value, Operand *output) {
+}
+
+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:
+#line 6933
+ CError_ASSERT(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:
+#line 6979
+ CError_FATAL();
+ }
+
+ 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:
+#line 7211
+ CError_FATAL();
+ }
+
+ output->optype = OpndType_GPRPair;
+ output->reg = reg;
+ output->regHi = regHi;
+}
+
+void I8_gen_XOR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+}
+
+void I8_gen_OR(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+}
+
+void I8_gen_AND(ENode *expr, short outputReg, short outputRegHi, Operand *output) {
+}
+
+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) {
+#line 7703
+ CError_FATAL();
+ }
+
+ 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 {
+#line 7732
+ CError_FATAL();
+ }
+}
+
+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) {
+#line 7756
+ CError_FATAL();
+ }
+
+ 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 {
+#line 7866
+ CError_FATAL();
+ }
+}
+
+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)) {
+#line 7900
+ CError_FATAL();
+ }
+
+ 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:
+#line 8097
+ CError_ASSERT(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:
+#line 8218
+ CError_FATAL();
+ }
+ }
+
+ 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 {
+#line 8328
+ CError_FATAL();
+ }
+ 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) {
+#line 8348
+ CError_FATAL();
+ } 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)) {
+#line 8376
+ CError_FATAL();
+ } 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;
+ }
+
+#line 8446
+ CError_ASSERT(!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:
+#line 8511
+ CError_FATAL();
+ }
+
+ output->reg = vi->reg;
+ output->regHi = vi->regHi;
+ output->object = NULL;
+ return;
+ }
+
+ if (ENODE_IS(inner, EBITFIELD)) {
+#line 8529
+ CError_FATAL();
+ 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;
+ }
+ }
+
+#line 8704
+ CError_ASSERT(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:
+#line 8814
+ CError_FATAL();
+ }
+}
+
+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;
+ }
+
+#line 8890
+ CError_ASSERT(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 {
+#line 8909
+ CError_FATAL();
+ }
+
+ 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)) {
+#line 8976
+ CError_ASSERT(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 {
+#line 9018
+ CError_FATAL();
+ }
+ } 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);
+
+#line 9048
+ CError_ASSERT(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 {
+#line 9074
+ CError_FATAL();
+ }
+
+ 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) {
+#line 9171
+ CError_ASSERT(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);
+#line 9200
+ CError_ASSERT(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)) {
+#line 9222
+ CError_FATAL();
+ 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 {
+#line 9256
+ CError_FATAL();
+ }
+ return;
+ }
+
+#line 9261
+ CError_FATAL();
+}
+
+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)) {
+#line 9282
+ CError_FATAL();
+ }
+
+ 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;
+ }
+
+#line 9298
+ CError_FATAL();
+}
diff --git a/compiler_and_linker/unsorted/InterferenceGraph.c b/compiler_and_linker/unsorted/InterferenceGraph.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/InterferenceGraph.c
diff --git a/compiler_and_linker/unsorted/Intrinsics.c b/compiler_and_linker/unsorted/Intrinsics.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Intrinsics.c
diff --git a/compiler_and_linker/unsorted/IrOptimizer.c b/compiler_and_linker/unsorted/IrOptimizer.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IrOptimizer.c
diff --git a/compiler_and_linker/unsorted/IroBitVect.c b/compiler_and_linker/unsorted/IroBitVect.c
new file mode 100644
index 0000000..ecaea04
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroBitVect.c
@@ -0,0 +1,114 @@
+#include "compiler/IroBitVect.h"
+#include "compiler/CompilerTools.h"
+
+void Bv_AllocVector(BitVector **bv, UInt32 size) {
+ UInt32 long_size = (size / 32) + 1;
+ *bv = oalloc(sizeof(BitVector) + sizeof(UInt32) * long_size);
+ (*bv)->size = long_size;
+ Bv_Clear(*bv);
+}
+
+void Bv_AllocVectorLocal(BitVector **bv, UInt32 size) {
+ UInt32 long_size = (size / 32) + 1;
+ *bv = lalloc(sizeof(BitVector) + sizeof(UInt32) * long_size);
+ (*bv)->size = long_size;
+ Bv_Clear(*bv);
+}
+
+void Bv_ClearBit(UInt32 bit, BitVector *bv) {
+ if ((bit / 32) < bv->size) {
+ bv->data[bit / 32] &= ~(1 << (bit & 31));
+ } else {
+#line 73
+ CError_FATAL();
+ }
+}
+
+void Bv_And(const BitVector *a, BitVector *b) {
+ UInt32 i;
+ for (i = 0; i < b->size; i++)
+ b->data[i] &= a->data[i];
+}
+
+void Bv_Or(const BitVector *a, BitVector *b) {
+ UInt32 i, len;
+
+ len = a->size;
+ if (b->size < len)
+ len = b->size;
+
+ for (i = 0; i < len; i++) {
+ b->data[i] |= a->data[i];
+ }
+}
+
+Boolean Bv_BitsInCommon(const BitVector *a, const BitVector *b) {
+ UInt32 len;
+ UInt32 i;
+
+ len = a->size;
+ if (b->size < len)
+ len = b->size;
+
+ for (i = 0; i < len; i++) {
+ if (a->data[i] & b->data[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+Boolean Bv_Compare(const BitVector *a, const BitVector *b) {
+ UInt32 i;
+ for (i = 0; i < a->size; i++) {
+ if (a->data[i] != b->data[i])
+ return 0;
+ }
+
+ return 1;
+}
+
+void Bv_Minus(const BitVector *a, BitVector *b) {
+ UInt32 i;
+ for (i = 0; i < b->size; i++)
+ b->data[i] &= ~a->data[i];
+}
+
+void Bv_Copy(const BitVector *src, BitVector *dst) {
+ memcpy(dst->data, src->data, sizeof(UInt32) * dst->size);
+}
+
+void Bv_Clear(BitVector *bv) {
+ memset(bv->data, 0, sizeof(UInt32) * bv->size);
+}
+
+void Bv_Set(BitVector *bv) {
+ memset(bv->data, 0xFF, sizeof(UInt32) * bv->size);
+}
+
+Boolean Bv_IsSubset(const BitVector *a, const BitVector *b) {
+ UInt32 i;
+
+ for (i = 0; i < a->size; i++) {
+ if (b->size < i) {
+ if (a->data[i])
+ return 0;
+ } else {
+ if (a->data[i] & ~(b->data[i]))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+Boolean Bv_IsEmpty(const BitVector *bv) {
+ UInt32 i;
+
+ for (i = 0; i < bv->size; i++) {
+ if (bv->data[i])
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/compiler_and_linker/unsorted/IroCSE.c b/compiler_and_linker/unsorted/IroCSE.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroCSE.c
diff --git a/compiler_and_linker/unsorted/IroDump.c b/compiler_and_linker/unsorted/IroDump.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroDump.c
diff --git a/compiler_and_linker/unsorted/IroEmptyLoop.c b/compiler_and_linker/unsorted/IroEmptyLoop.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroEmptyLoop.c
diff --git a/compiler_and_linker/unsorted/IroEval.c b/compiler_and_linker/unsorted/IroEval.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroEval.c
diff --git a/compiler_and_linker/unsorted/IroExprRegeneration.c b/compiler_and_linker/unsorted/IroExprRegeneration.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroExprRegeneration.c
diff --git a/compiler_and_linker/unsorted/IroFlowgraph.c b/compiler_and_linker/unsorted/IroFlowgraph.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroFlowgraph.c
diff --git a/compiler_and_linker/unsorted/IroJump.c b/compiler_and_linker/unsorted/IroJump.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroJump.c
diff --git a/compiler_and_linker/unsorted/IroLinearForm.c b/compiler_and_linker/unsorted/IroLinearForm.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroLinearForm.c
diff --git a/compiler_and_linker/unsorted/IroLoop.c b/compiler_and_linker/unsorted/IroLoop.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroLoop.c
diff --git a/compiler_and_linker/unsorted/IroMalloc.c b/compiler_and_linker/unsorted/IroMalloc.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroMalloc.c
diff --git a/compiler_and_linker/unsorted/IroPointerAnalysis.c b/compiler_and_linker/unsorted/IroPointerAnalysis.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroPointerAnalysis.c
diff --git a/compiler_and_linker/unsorted/IroPropagate.c b/compiler_and_linker/unsorted/IroPropagate.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroPropagate.c
diff --git a/compiler_and_linker/unsorted/IroRangePropagation.c b/compiler_and_linker/unsorted/IroRangePropagation.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroRangePropagation.c
diff --git a/compiler_and_linker/unsorted/IroSubable.c b/compiler_and_linker/unsorted/IroSubable.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroSubable.c
diff --git a/compiler_and_linker/unsorted/IroTransform.c b/compiler_and_linker/unsorted/IroTransform.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroTransform.c
diff --git a/compiler_and_linker/unsorted/IroUnrollLoop.c b/compiler_and_linker/unsorted/IroUnrollLoop.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroUnrollLoop.c
diff --git a/compiler_and_linker/unsorted/IroUtil.c b/compiler_and_linker/unsorted/IroUtil.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroUtil.c
diff --git a/compiler_and_linker/unsorted/IroVars.c b/compiler_and_linker/unsorted/IroVars.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/IroVars.c
diff --git a/compiler_and_linker/unsorted/LoadDeletion.c b/compiler_and_linker/unsorted/LoadDeletion.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/LoadDeletion.c
diff --git a/compiler_and_linker/unsorted/LoopDetection.c b/compiler_and_linker/unsorted/LoopDetection.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/LoopDetection.c
diff --git a/compiler_and_linker/unsorted/LoopOptimization.c b/compiler_and_linker/unsorted/LoopOptimization.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/LoopOptimization.c
diff --git a/compiler_and_linker/unsorted/MachO.c b/compiler_and_linker/unsorted/MachO.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/MachO.c
diff --git a/compiler_and_linker/unsorted/ObjGenMachO.c b/compiler_and_linker/unsorted/ObjGenMachO.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/ObjGenMachO.c
diff --git a/compiler_and_linker/unsorted/Operands.c b/compiler_and_linker/unsorted/Operands.c
index c0fee65..68883e0 100644
--- a/compiler_and_linker/unsorted/Operands.c
+++ b/compiler_and_linker/unsorted/Operands.c
@@ -75,12 +75,12 @@ void indirect(Operand *op, ENode *expr) {
set_op_flags(op, expr);
break;
case OpndType_Absolute:
- if (FITS_IN_SHORT(op->abs_address)) {
+ if (FITS_IN_SHORT(op->immediate)) {
op->reg = 0;
- op->immOffset = op->abs_address;
+ op->immOffset = op->immediate;
} else {
- emitpcode(PC_LIS, op->reg = used_virtual_registers[RegClass_GPR]++, 0, (short) HIGH_PART(op->abs_address));
- op->immOffset = LOW_PART(op->abs_address);
+ 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;
@@ -201,27 +201,27 @@ void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
opOut->reg = opB->reg;
opOut->immOffset = opB->immOffset;
opOut->object = opB->object;
- if (FITS_IN_SHORT(opOut->immOffset + opA->abs_address)) {
- opOut->immOffset += opA->abs_address;
+ 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->abs_address)) {
- emitpcode(PC_ADDI, opOut->reg, opB->reg, 0, LOW_PART(opA->abs_address));
+ 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->abs_address));
- if (FITS_IN_SHORT(opOut->immOffset + LOW_PART(opA->abs_address))) {
- opOut->immOffset += LOW_PART(opA->abs_address);
+ 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->abs_address));
+ 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->abs_address)) {
+ } 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->abs_address);
+ opOut->immOffset = LOW_PART(opB->immOffset + opA->immediate);
break;
} else {
opOut->reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
@@ -237,14 +237,14 @@ void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
opA = opB;
opB = tmp_op;
case COMBO_OP(OpndType_Absolute, OpndType_GPR):
- opOut->optype = (opA->abs_address != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR;
- opOut->immOffset = LOW_PART(opA->abs_address);
+ opOut->optype = (opA->immediate != 0) ? OpndType_GPR_ImmOffset : OpndType_GPR;
+ opOut->immOffset = LOW_PART(opA->immediate);
opOut->object = NULL;
- if (FITS_IN_SHORT(opA->abs_address)) {
+ 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->abs_address));
+ emitpcode(PC_ADDIS, opOut->reg, opB->reg, 0, (short) HIGH_PART(opA->immediate));
}
break;
case COMBO_OP(OpndType_GPR_Indexed, OpndType_Absolute):
@@ -255,17 +255,17 @@ void combine(Operand *opA, Operand *opB, short output_reg, Operand *opOut) {
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->abs_address)) {
- emitpcode(PC_ADDI, opOut->regOffset, opB->regOffset, 0, LOW_PART(opA->abs_address));
+ 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->abs_address));
- if (opA->abs_address != 0)
- emitpcode(PC_ADDI, opOut->regOffset, opOut->regOffset, 0, LOW_PART(opA->abs_address));
+ emitpcode(PC_ADDIS, opOut->regOffset, opB->regOffset, 0, (short) HIGH_PART(opA->immediate));
+ if (opA->immediate != 0)
+ 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->abs_address = opA->abs_address + opB->abs_address;
+ opOut->immediate = opA->immediate + opB->immediate;
break;
default:
#line 415
@@ -344,7 +344,6 @@ void coerce_to_addressable(Operand *op) {
}
}
-void Coerce_to_register(Operand *op, Type *type, short output_reg) {
SInt32 offset;
short opcode;
short reg;
@@ -375,7 +374,7 @@ void Coerce_to_register(Operand *op, Type *type, short output_reg) {
break;
case OpndType_Absolute:
reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- offset = op->abs_address;
+ offset = op->immediate;
if (FITS_IN_SHORT(offset)) {
emitpcode(PC_LI, reg, offset);
} else {
@@ -534,7 +533,7 @@ void coerce_to_register_pair(Operand *op, Type *type, short output_reg, short ou
break;
case OpndType_Absolute:
reg = output_reg ? output_reg : used_virtual_registers[RegClass_GPR]++;
- offset = op->abs_address;
+ offset = op->immediate;
if (FITS_IN_SHORT(offset)) {
emitpcode(PC_LI, reg, offset);
} else {
@@ -648,19 +647,19 @@ void Coerce_to_v_register(Operand *op, TypeStruct *tstruct, short output_reg) {
case STRUCT_TYPE_4:
case STRUCT_TYPE_5:
case STRUCT_TYPE_6:
- emitpcode(PC_VSPLTISB, reg, op->abs_address);
+ emitpcode(PC_VSPLTISB, reg, op->immediate);
break;
case STRUCT_TYPE_7:
case STRUCT_TYPE_8:
case STRUCT_TYPE_9:
case STRUCT_TYPE_E:
- emitpcode(PC_VSPLTISH, reg, op->abs_address);
+ emitpcode(PC_VSPLTISH, reg, op->immediate);
break;
case STRUCT_TYPE_A:
case STRUCT_TYPE_B:
case STRUCT_TYPE_C:
case STRUCT_TYPE_D:
- emitpcode(PC_VSPLTISW, reg, op->abs_address);
+ emitpcode(PC_VSPLTISW, reg, op->immediate);
break;
default:
#line 1049
@@ -754,7 +753,7 @@ void store_pair(short reg, short regHi, Operand *op, Type *type) {
}
}
-void store_fp(short reg, Operand *op, TypeIntegral *tint) {
+void store_fp(short reg, Operand *op, Type *tint) {
coerce_to_addressable(op);
switch (op->optype) {
case OpndType_IndirectGPR_ImmOffset:
@@ -771,7 +770,7 @@ void store_fp(short reg, Operand *op, TypeIntegral *tint) {
}
}
-void store_v(short reg, Operand *op, TypeStruct *tstruct) {
+void store_v(short reg, Operand *op, Type *tstruct) {
coerce_to_addressable(op);
switch (op->optype) {
case OpndType_IndirectGPR_ImmOffset:
@@ -880,7 +879,7 @@ void extend64(Operand *op, Type *type, short output_reg, short output_regHi) {
op->regHi = regHi;
}
-void load_floating_constant(short reg, TypeIntegral *type, double *data) {
+void load_floating_constant(short reg, Type *type, double *data) {
// do me AFTER
}
diff --git a/compiler_and_linker/unsorted/PCode.c b/compiler_and_linker/unsorted/PCode.c
index 0fde159..f53030b 100644
--- a/compiler_and_linker/unsorted/PCode.c
+++ b/compiler_and_linker/unsorted/PCode.c
@@ -1,18 +1,22 @@
-#include "compiler.h"
#include "compiler/CompilerTools.h"
+#include "compiler/CFunc.h"
+#include "compiler/CodeGen.h"
#include "compiler/PCode.h"
#include "compiler/PCodeInfo.h"
+// TODO: move me
+extern void initialize_aliases();
+
PCodeBlock *pcbasicblocks;
PCodeBlock *pclastblock;
-void *prologue;
-void *epilogue;
+PCodeBlock *prologue;
+PCodeBlock *epilogue;
PCodeBlock **depthfirstordering;
int pcblockcount;
int pcloopweight;
static unsigned short pclabelcount;
-void initpcode() {
+void initpcode(void) {
pclastblock = 0;
pcbasicblocks = 0;
pcblockcount = 0;
@@ -21,7 +25,7 @@ void initpcode() {
initialize_aliases();
}
-PCode *makepcode(short op, ...) {
+PCode *makepcode(Opcode op, ...) {
PCode *pcode;
va_list list;
@@ -31,7 +35,7 @@ PCode *makepcode(short op, ...) {
return pcode;
}
-void emitpcode(short op, ...) {
+void emitpcode(Opcode op, ...) {
PCode *pcode;
va_list list;
@@ -67,7 +71,7 @@ PCode *copypcode(PCode *pcode) {
return newpc;
}
-PCodeLabel *makepclabel() {
+PCodeLabel *makepclabel(void) {
PCodeLabel *label;
label = (PCodeLabel *) lalloc(sizeof(PCodeLabel));
@@ -76,7 +80,7 @@ PCodeLabel *makepclabel() {
return label;
}
-PCodeBlock *makepcblock() {
+PCodeBlock *makepcblock(void) {
PCodeBlock *block;
block = (PCodeBlock *) lalloc(sizeof(PCodeBlock));
@@ -123,7 +127,7 @@ void pcbranch(PCodeBlock *block, PCodeLabel *label) {
block->successors = link;
}
-void pccomputepredecessors() {
+void pccomputepredecessors(void) {
PCodeBlock *block;
PCLink *succ;
PCLink *pred;
@@ -147,7 +151,7 @@ void deleteblock(PCodeBlock *block) {
block->flags |= fPCBlockFlag20;
}
-void deleteunreachableblocks() {
+void deleteunreachableblocks(void) {
PCodeBlock *block;
computedepthfirstordering();
@@ -238,7 +242,7 @@ void clearpcodeflags(int flags) {
pclastblock->lastPCode->flags &= ~flags;
}
-int pccomputeoffsets() {
+int pccomputeoffsets(void) {
int offset;
PCodeBlock *block;
@@ -258,7 +262,7 @@ typedef struct _DFO {
static int depthfirstorder;
-void computedepthfirstordering() {
+void computedepthfirstordering(void) {
PCodeBlock *block;
PCLink *link;
DFO *dfo;
diff --git a/compiler_and_linker/unsorted/PCodeAssembly.c b/compiler_and_linker/unsorted/PCodeAssembly.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/PCodeAssembly.c
diff --git a/compiler_and_linker/unsorted/PCodeInfo.c b/compiler_and_linker/unsorted/PCodeInfo.c
index e48dac0..3646930 100644
--- a/compiler_and_linker/unsorted/PCodeInfo.c
+++ b/compiler_and_linker/unsorted/PCodeInfo.c
@@ -90,7 +90,7 @@ int pcode_check_imm_bits(SInt32 value, int bits, char typechar) {
return 0;
}
-int pcode_const_from_format(const char *format, int *pResult) {
+int pcode_const_from_format(const char *format, SInt32 *pResult) {
char buf[32];
int len = 0;
diff --git a/compiler_and_linker/unsorted/PCodeListing.c b/compiler_and_linker/unsorted/PCodeListing.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/PCodeListing.c
diff --git a/compiler_and_linker/unsorted/PPCError.c b/compiler_and_linker/unsorted/PPCError.c
new file mode 100644
index 0000000..2ba28bd
--- /dev/null
+++ b/compiler_and_linker/unsorted/PPCError.c
@@ -0,0 +1,71 @@
+#include "compiler/PPCError.h"
+#include "compiler/CError.h"
+#include "compiler/CParser.h"
+#include "compiler/InlineAsm.h"
+#include "cos.h"
+
+static void PPCError_GetErrorString(char *str, short code) {
+ short scode;
+
+ scode = (short) code;
+#line 40
+ CError_ASSERT(scode >= 100 && scode < 212);
+
+ COS_GetString(str, 10001, scode - 99);
+}
+
+static void PPCError_VAErrorMessage(int code, va_list list, Boolean flag1, Boolean flag2) {
+ char format[256];
+ PPCError_GetErrorString(format, code);
+ CError_ErrorMessageVA(code + 10001, format, list, flag1, flag2);
+}
+
+void PPCError_Error(int code, ...) {
+ va_list list;
+
+ if (trychain)
+ longjmp(trychain->jmpbuf, 1);
+
+ va_start(list, code);
+ PPCError_VAErrorMessage(code, list, 0, 0);
+ va_end(list);
+
+ if (in_assembler)
+ AssemblerError();
+}
+
+void PPCError_Warning(int code, ...) {
+ va_list list;
+
+ if (!trychain) {
+ va_start(list, code);
+ PPCError_VAErrorMessage(code, list, 0, 1);
+ va_end(list);
+ }
+}
+
+void PPCError_Message(char *format, ...) {
+ va_list list;
+
+ if (!trychain) {
+ va_start(list, format);
+ CError_ErrorMessageVA(10213, format, list, 0, 1);
+ va_end(list);
+ }
+}
+
+void PPCError_ErrorTerm(short code, ...) {
+ va_list list;
+
+ if (trychain)
+ longjmp(trychain->jmpbuf, 1);
+
+ va_start(list, code);
+ PPCError_VAErrorMessage(code, list, 1, 0);
+ va_end(list);
+
+ if (in_assembler)
+ AssemblerError();
+
+ longjmp(errorreturn, 1);
+}
diff --git a/compiler_and_linker/unsorted/Peephole.c b/compiler_and_linker/unsorted/Peephole.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Peephole.c
diff --git a/compiler_and_linker/unsorted/RegisterInfo.c b/compiler_and_linker/unsorted/RegisterInfo.c
index c1e67d8..80e348d 100644
--- a/compiler_and_linker/unsorted/RegisterInfo.c
+++ b/compiler_and_linker/unsorted/RegisterInfo.c
@@ -1,7 +1,11 @@
-#include "compiler.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/CodeGen.h"
#include "compiler/CError.h"
-#include "compiler/objects.h"
+#include "compiler/CParser.h"
#include "compiler/PCode.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
+#include "compiler/types.h"
short last_exception_register[RegClassMax];
short first_fe_temporary_register[RegClassMax];
@@ -12,8 +16,6 @@ char *special_register_names[RegClassMax][RegisterMax];
static short used_regs_before_coloring;
static UInt8 save_state[RegisterMax];
-char *XXspecial_register_names[RegClassMax * RegisterMax];
-
short spr_to_sysreg[4] = {1, 8, 9, 0x100};
void asm_used_register(char rclass, short reg) {
@@ -104,7 +106,7 @@ static int first_nonvolatile_reg(char rclass) {
return GetABIFirstNonVolatile(rclass);
}
-void setup_diagnostic_reg_strings() {
+void setup_diagnostic_reg_strings(void) {
register_class_name[RegClass_SPR] = "SPR";
register_class_format[RegClass_SPR] = "spr%ld";
register_class_name[RegClass_CRFIELD] = "CRFIELD";
@@ -117,7 +119,7 @@ void setup_diagnostic_reg_strings() {
register_class_format[RegClass_GPR] = "r%ld";
}
-void init_target_registers() {
+void init_target_registers(void) {
char rclass;
int reg;
int end;
@@ -244,7 +246,7 @@ void assign_GPR_pair(Object *obj) {
}
}
-void open_fe_temp_registers() {
+void open_fe_temp_registers(void) {
int r;
r = used_virtual_registers[RegClass_GPR];
@@ -258,13 +260,13 @@ void open_fe_temp_registers() {
//first_fe_temporary_register[RegClass_VR] = last_temporary_register[RegClass_VR] = used_virtual_registers[RegClass_VR];
}
-void set_last_exception_registers() {
+void set_last_exception_registers(void) {
last_exception_register[RegClass_GPR] = used_virtual_registers[RegClass_GPR] - 1;
last_exception_register[RegClass_FPR] = used_virtual_registers[RegClass_FPR] - 1;
last_exception_register[RegClass_VR] = used_virtual_registers[RegClass_VR] - 1;
}
-static VarInfo *Registers_GetNewVarInfo() {
+static VarInfo *Registers_GetNewVarInfo(void) {
VarInfo *vi = galloc(sizeof(VarInfo));
memclrw(vi, sizeof(VarInfo));
return vi;
@@ -302,7 +304,7 @@ VarInfo *Registers_GetVarInfo(Object *obj) {
}
}
-int used_vrstate_VRs() {
+int used_vrstate_VRs(void) {
int count = 0;
int i;
for (i = 0; i < RegisterMax; i++) {
@@ -318,9 +320,9 @@ UInt32 colored_vrs_as_vrsave(PCodeBlock *block) {
int i;
mask = 0;
- if (copts.x1B == 2)
+ if (copts.altivec_vrsave == 2)
return 0xFFFFFFFF;
- if (copts.x1B == 0)
+ if (copts.altivec_vrsave == 0)
return 0;
while (block) {
@@ -359,7 +361,7 @@ int is_nonvolatile_register(char rclass, int reg) {
return 0;
}
-void init_endian() {
+void init_endian(void) {
if (copts.little_endian) {
high_offset = 4;
low_offset = 0;
@@ -377,7 +379,7 @@ void init_endian() {
}
}
-void update_asm_nonvolatile_registers() {
+void update_asm_nonvolatile_registers(void) {
char rclass;
int r31;
diff --git a/compiler_and_linker/unsorted/Registers.c b/compiler_and_linker/unsorted/Registers.c
index 9bcbf05..b8951b7 100644
--- a/compiler_and_linker/unsorted/Registers.c
+++ b/compiler_and_linker/unsorted/Registers.c
@@ -1,6 +1,9 @@
-#include "compiler.h"
-#include "compiler/objects.h"
+#include "compiler/Registers.h"
+#include "compiler/RegisterInfo.h"
+#include "compiler/CParser.h"
#include "compiler/PCode.h"
+#include "compiler/CompilerTools.h"
+#include "compiler/objects.h"
// haven't checked this object file for .data stuff yet
@@ -30,7 +33,7 @@ typedef struct ModifiedRegisters {
} ModifiedRegisters;
static ModifiedRegisters *mod_regs_table[128];
-void init_registers() {
+void init_registers(void) {
char rclass;
int j;
@@ -117,7 +120,7 @@ short obtain_nonvolatile_register(char rclass) {
return best;
}
-void open_temp_registers() {
+void open_temp_registers(void) {
int rclass;
for (rclass = 0; (char)rclass < RegClassMax; rclass++) {
@@ -135,7 +138,7 @@ void open_temp_registers() {
}*/
}
-void check_temp_registers() {
+void check_temp_registers(void) {
char rclass;
if (!optimizing) {
@@ -148,7 +151,7 @@ void check_temp_registers() {
}
}
-void close_temp_registers() {
+void close_temp_registers(void) {
char rclass;
for (rclass = 0; rclass < RegClassMax; rclass++) {
@@ -159,7 +162,7 @@ void close_temp_registers() {
}
}
-int count_scratch_registers() {
+int count_scratch_registers(void) {
int rclass;
int count;
@@ -169,7 +172,7 @@ int count_scratch_registers() {
return count;
}
-void init_modified_registers() {
+void init_modified_registers(void) {
int i = 0;
for (i = 0; i < 128; i++)
diff --git a/compiler_and_linker/unsorted/Scheduler.c b/compiler_and_linker/unsorted/Scheduler.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Scheduler.c
diff --git a/compiler_and_linker/unsorted/SpillCode.c b/compiler_and_linker/unsorted/SpillCode.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/SpillCode.c
diff --git a/compiler_and_linker/unsorted/StackFrame.c b/compiler_and_linker/unsorted/StackFrame.c
index 5789cb5..18cb6fd 100644
--- a/compiler_and_linker/unsorted/StackFrame.c
+++ b/compiler_and_linker/unsorted/StackFrame.c
@@ -64,7 +64,7 @@ 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 flag1, int reg1, int reg2, SInt32 size);
-void init_stack_globals(void) {
+void init_stack_globals(Object *funcobj) {
char rclass;
UInt8 oclass;
@@ -115,7 +115,7 @@ void init_stack_globals(void) {
}
}
-void init_frame_sizes(void) {
+void init_frame_sizes(Boolean has_varargs) {
ObjectList *scan;
Object *obj;
SInt32 r30;
@@ -326,7 +326,7 @@ static void allocate_new_frame(int reg1, int reg2) {
}
}
-void generate_prologue(PCodeBlock *block) {
+void generate_prologue(PCodeBlock *block, Boolean has_varargs) {
PCodeBlock *save_block;
Boolean needs_lr;
Statement *save_statement;
diff --git a/compiler_and_linker/unsorted/StrengthReduction.c b/compiler_and_linker/unsorted/StrengthReduction.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/StrengthReduction.c
diff --git a/compiler_and_linker/unsorted/StructMoves.c b/compiler_and_linker/unsorted/StructMoves.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/StructMoves.c
diff --git a/compiler_and_linker/unsorted/Switch.c b/compiler_and_linker/unsorted/Switch.c
new file mode 100644
index 0000000..af62eb3
--- /dev/null
+++ b/compiler_and_linker/unsorted/Switch.c
@@ -0,0 +1,78 @@
+#include "compiler/Switch.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/objects.h"
+#include "compiler/CParser.h"
+#include "compiler/PCode.h"
+
+ObjectList *switchtables;
+static void *caselabels;
+static void *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 void compare_cases() {
+}
+
+static void build_case_ranges(Type *type, SwitchCase *cases, CLabel *label) {
+}
+
+static void treecompare() {
+}
+
+static void I8_treecompare() {
+}
+
+static void generate_tree(ENode *expr) {
+}
+
+static void create_switch_table() {
+}
+
+static void generate_table(ENode *expr, SwitchInfo *info) {
+}
+
+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++;
+ }
+
+#line 656
+ CError_ASSERT(ncases >= 0 && ncases <= 0x3333332);
+
+ 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 / 1) + 4))
+ generate_tree(expr);
+ else
+ generate_table(expr, info);
+}
+
+void dumpswitchtables(Object *funcobj) {
+}
diff --git a/compiler_and_linker/unsorted/TOC.c b/compiler_and_linker/unsorted/TOC.c
index 65dc39b..0f3024f 100644
--- a/compiler_and_linker/unsorted/TOC.c
+++ b/compiler_and_linker/unsorted/TOC.c
@@ -1,15 +1,21 @@
#include "cos.h"
#include "compiler/TOC.h"
+#include "compiler/CDecl.h"
#include "compiler/CError.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/Operands.h"
#include "compiler/PCode.h"
#include "compiler/PCodeInfo.h"
#include "compiler/StackFrame.h"
+#include "compiler/CompilerTools.h"
#include "compiler/enode.h"
#include "compiler/objects.h"
#include "compiler/types.h"
-#include "compiler.h"
ObjectList *toclist;
ObjectList *exceptionlist;
diff --git a/compiler_and_linker/unsorted/Unmangle.c b/compiler_and_linker/unsorted/Unmangle.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/Unmangle.c
diff --git a/compiler_and_linker/unsorted/UseDefChains.c b/compiler_and_linker/unsorted/UseDefChains.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/UseDefChains.c
diff --git a/compiler_and_linker/unsorted/ValueNumbering.c b/compiler_and_linker/unsorted/ValueNumbering.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/ValueNumbering.c
diff --git a/compiler_and_linker/unsorted/VectorArraysToRegs.c b/compiler_and_linker/unsorted/VectorArraysToRegs.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compiler_and_linker/unsorted/VectorArraysToRegs.c