#include "compiler/CMachine.h" #include "compiler/CClass.h" #include "compiler/CError.h" #include "compiler/CInt64.h" #include "compiler/CParser.h" #include "compiler/CPrep.h" #include "compiler/CPrepTokenizer.h" #include "compiler/CompilerTools.h" #include "compiler/objects.h" #include "compiler/types.h" TypeIntegral stbool = {TYPEINT, 0, IT_BOOL}; TypeIntegral stchar = {TYPEINT, 1, IT_CHAR}; TypeIntegral stsignedchar = {TYPEINT, 0, IT_SCHAR}; TypeIntegral stunsignedchar = {TYPEINT, 0, IT_UCHAR}; TypeIntegral stwchar = {TYPEINT, 4, IT_WCHAR_T}; TypeIntegral stsignedshort = {TYPEINT, 2, IT_SHORT}; TypeIntegral stunsignedshort = {TYPEINT, 2, IT_USHORT}; TypeIntegral stsignedint = {TYPEINT, 4, IT_INT}; TypeIntegral stunsignedint = {TYPEINT, 4, IT_UINT}; TypeIntegral stsignedlong = {TYPEINT, 4, IT_LONG}; TypeIntegral stunsignedlong = {TYPEINT, 4, IT_ULONG}; TypeIntegral stsignedlonglong = {TYPEINT, 8, IT_LONGLONG}; TypeIntegral stunsignedlonglong = {TYPEINT, 8, IT_ULONGLONG}; TypeIntegral stfloat = {TYPEFLOAT, 4, IT_FLOAT}; TypeIntegral stshortdouble = {TYPEINT, 8, IT_SHORTDOUBLE}; TypeIntegral stdouble = {TYPEINT, 8, IT_DOUBLE}; TypeIntegral stlongdouble = {TYPEINT, 8, IT_LONGDOUBLE}; static StructMember stVUC_unsignedchar15 = {NULL, (Type *) &stunsignedchar, NULL, 15, 0}; static StructMember stVUC_unsignedchar14 = {&stVUC_unsignedchar15, (Type *) &stunsignedchar, NULL, 14, 0}; static StructMember stVUC_unsignedchar13 = {&stVUC_unsignedchar14, (Type *) &stunsignedchar, NULL, 13, 0}; static StructMember stVUC_unsignedchar12 = {&stVUC_unsignedchar13, (Type *) &stunsignedchar, NULL, 12, 0}; static StructMember stVUC_unsignedchar11 = {&stVUC_unsignedchar12, (Type *) &stunsignedchar, NULL, 11, 0}; static StructMember stVUC_unsignedchar10 = {&stVUC_unsignedchar11, (Type *) &stunsignedchar, NULL, 10, 0}; static StructMember stVUC_unsignedchar9 = {&stVUC_unsignedchar10, (Type *) &stunsignedchar, NULL, 9, 0}; static StructMember stVUC_unsignedchar8 = {&stVUC_unsignedchar9, (Type *) &stunsignedchar, NULL, 8, 0}; static StructMember stVUC_unsignedchar7 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 7, 0}; static StructMember stVUC_unsignedchar6 = {&stVUC_unsignedchar7, (Type *) &stunsignedchar, NULL, 6, 0}; static StructMember stVUC_unsignedchar5 = {&stVUC_unsignedchar6, (Type *) &stunsignedchar, NULL, 5, 0}; static StructMember stVUC_unsignedchar4 = {&stVUC_unsignedchar5, (Type *) &stunsignedchar, NULL, 4, 0}; static StructMember stVUC_unsignedchar3 = {&stVUC_unsignedchar4, (Type *) &stunsignedchar, NULL, 3, 0}; static StructMember stVUC_unsignedchar2 = {&stVUC_unsignedchar3, (Type *) &stunsignedchar, NULL, 2, 0}; static StructMember stVUC_unsignedchar1 = {&stVUC_unsignedchar2, (Type *) &stunsignedchar, NULL, 1, 0}; static StructMember stVUC_unsignedchar0 = {&stVUC_unsignedchar1, (Type *) &stunsignedchar, NULL, 0, 0}; static StructMember stVSC_signedchar15 = {NULL, (Type *) &stsignedchar, NULL, 15, 0}; static StructMember stVSC_signedchar14 = {&stVSC_signedchar15, (Type *) &stsignedchar, NULL, 14, 0}; static StructMember stVSC_signedchar13 = {&stVSC_signedchar14, (Type *) &stsignedchar, NULL, 13, 0}; static StructMember stVSC_signedchar12 = {&stVSC_signedchar13, (Type *) &stsignedchar, NULL, 12, 0}; static StructMember stVSC_signedchar11 = {&stVSC_signedchar12, (Type *) &stsignedchar, NULL, 11, 0}; static StructMember stVSC_signedchar10 = {&stVSC_signedchar11, (Type *) &stsignedchar, NULL, 10, 0}; static StructMember stVSC_signedchar9 = {&stVSC_signedchar10, (Type *) &stsignedchar, NULL, 9, 0}; static StructMember stVSC_signedchar8 = {&stVSC_signedchar9, (Type *) &stsignedchar, NULL, 8, 0}; static StructMember stVSC_signedchar7 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 7, 0}; static StructMember stVSC_signedchar6 = {&stVSC_signedchar7, (Type *) &stsignedchar, NULL, 6, 0}; static StructMember stVSC_signedchar5 = {&stVSC_signedchar6, (Type *) &stsignedchar, NULL, 5, 0}; static StructMember stVSC_signedchar4 = {&stVSC_signedchar5, (Type *) &stsignedchar, NULL, 4, 0}; static StructMember stVSC_signedchar3 = {&stVSC_signedchar4, (Type *) &stsignedchar, NULL, 3, 0}; static StructMember stVSC_signedchar2 = {&stVSC_signedchar3, (Type *) &stsignedchar, NULL, 2, 0}; static StructMember stVSC_signedchar1 = {&stVSC_signedchar2, (Type *) &stsignedchar, NULL, 1, 0}; static StructMember stVSC_signedchar0 = {&stVSC_signedchar1, (Type *) &stsignedchar, NULL, 0, 0}; static StructMember stVUS_unsignedshort7 = {NULL, (Type *) &stunsignedshort, NULL, 14, 0}; static StructMember stVUS_unsignedshort6 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 12, 0}; static StructMember stVUS_unsignedshort5 = {&stVUS_unsignedshort7, (Type *) &stunsignedshort, NULL, 10, 0}; static StructMember stVUS_unsignedshort4 = {&stVUS_unsignedshort5, (Type *) &stunsignedshort, NULL, 8, 0}; static StructMember stVUS_unsignedshort3 = {&stVUS_unsignedshort4, (Type *) &stunsignedshort, NULL, 6, 0}; static StructMember stVUS_unsignedshort2 = {&stVUS_unsignedshort3, (Type *) &stunsignedshort, NULL, 4, 0}; static StructMember stVUS_unsignedshort1 = {&stVUS_unsignedshort2, (Type *) &stunsignedshort, NULL, 2, 0}; static StructMember stVUS_unsignedshort0 = {&stVUS_unsignedshort1, (Type *) &stunsignedshort, NULL, 0, 0}; static StructMember stVSS_signedshort7 = {NULL, (Type *) &stsignedshort, NULL, 14, 0}; static StructMember stVSS_signedshort6 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 12, 0}; static StructMember stVSS_signedshort5 = {&stVSS_signedshort7, (Type *) &stsignedshort, NULL, 10, 0}; static StructMember stVSS_signedshort4 = {&stVSS_signedshort5, (Type *) &stsignedshort, NULL, 8, 0}; static StructMember stVSS_signedshort3 = {&stVSS_signedshort4, (Type *) &stsignedshort, NULL, 6, 0}; static StructMember stVSS_signedshort2 = {&stVSS_signedshort3, (Type *) &stsignedshort, NULL, 4, 0}; static StructMember stVSS_signedshort1 = {&stVSS_signedshort2, (Type *) &stsignedshort, NULL, 2, 0}; static StructMember stVSS_signedshort0 = {&stVSS_signedshort1, (Type *) &stsignedshort, NULL, 0, 0}; static StructMember stVUL_unsignedlong3 = {NULL, (Type *) &stunsignedlong, NULL, 12, 0}; static StructMember stVUL_unsignedlong2 = {&stVUL_unsignedlong3, (Type *) &stunsignedlong, NULL, 8, 0}; static StructMember stVUL_unsignedlong1 = {&stVUL_unsignedlong2, (Type *) &stunsignedlong, NULL, 4, 0}; static StructMember stVUL_unsignedlong0 = {&stVUL_unsignedlong1, (Type *) &stunsignedlong, NULL, 0, 0}; static StructMember stVSL_signedlong3 = {NULL, (Type *) &stsignedlong, NULL, 12, 0}; static StructMember stVSL_signedlong2 = {&stVSL_signedlong3, (Type *) &stsignedlong, NULL, 8, 0}; static StructMember stVSL_signedlong1 = {&stVSL_signedlong2, (Type *) &stsignedlong, NULL, 4, 0}; static StructMember stVSL_signedlong0 = {&stVSL_signedlong1, (Type *) &stsignedlong, NULL, 0, 0}; static StructMember stVF_float3 = {NULL, (Type *) &stfloat, NULL, 12, 0}; static StructMember stVF_float2 = {&stVF_float3, (Type *) &stfloat, NULL, 8, 0}; static StructMember stVF_float1 = {&stVF_float2, (Type *) &stfloat, NULL, 4, 0}; static StructMember stVF_float0 = {&stVF_float1, (Type *) &stfloat, NULL, 0, 0}; TypeStruct stvectorunsignedchar = {TYPESTRUCT, 16, NULL, &stVUC_unsignedchar0, STRUCT_TYPE_4, 16}; TypeStruct stvectorsignedchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_TYPE_5, 16}; TypeStruct stvectorboolchar = {TYPESTRUCT, 16, NULL, &stVSC_signedchar0, STRUCT_TYPE_6, 16}; TypeStruct stvectorunsignedshort = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_TYPE_7, 16}; TypeStruct stvectorsignedshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_TYPE_8, 16}; TypeStruct stvectorboolshort = {TYPESTRUCT, 16, NULL, &stVSS_signedshort0, STRUCT_TYPE_9, 16}; TypeStruct stvectorunsignedlong = {TYPESTRUCT, 16, NULL, &stVUL_unsignedlong0, STRUCT_TYPE_A, 16}; TypeStruct stvectorsignedlong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_TYPE_B, 16}; TypeStruct stvectorboollong = {TYPESTRUCT, 16, NULL, &stVSL_signedlong0, STRUCT_TYPE_C, 16}; TypeStruct stvectorfloat = {TYPESTRUCT, 16, NULL, &stVF_float0, STRUCT_TYPE_D, 16}; TypeStruct stvectorpixel = {TYPESTRUCT, 16, NULL, &stVUS_unsignedshort0, STRUCT_TYPE_E, 16}; TypeStruct stvector = {TYPESTRUCT, 16, NULL, NULL, STRUCT_TYPE_A, 16}; static SInt32 cmach_structoffset; static UInt8 cmach_structalign; static short cmach_curbfsize; static short cmach_curbfbasesize; static int cmach_curbfoffset; static short cmach_packsize[] = { 1, 2, 4, 8, 16 }; // forward declarations static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag); static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 align, Boolean flag); void CMach_Configure() { } SInt32 CMach_GetQUALalign(UInt32 qual) { SInt32 result = 0; SInt32 chk; if ((chk = (qual & Q_ALIGNED_MASK))) { if (chk == Q_ALIGNED_1) result = 1; else if (chk == Q_ALIGNED_2) result = 2; else if (chk == Q_ALIGNED_4) result = 4; else if (chk == Q_ALIGNED_8) result = 8; else if (chk == Q_ALIGNED_16) result = 16; else if (chk == Q_ALIGNED_32) result = 32; else if (chk == Q_ALIGNED_64) result = 64; else if (chk == Q_ALIGNED_128) result = 128; else if (chk == Q_ALIGNED_256) result = 256; else if (chk == Q_ALIGNED_512) result = 512; else if (chk == Q_ALIGNED_1024) result = 1024; else if (chk == Q_ALIGNED_2048) result = 2048; else if (chk == Q_ALIGNED_4096) result = 4096; else if (chk == Q_ALIGNED_8192) result = 8192; else CError_FATAL(226); } return result; } SInt32 CMach_ArgumentAlignment(Type *type) { // does not match - registers UInt8 save_align_mode; UInt8 save_oldalignment; SInt32 align; save_align_mode = copts.align_mode; save_oldalignment = copts.oldalignment; copts.align_mode = AlignMode2_PPC; copts.oldalignment = 0; align = CMach_GetQualifiedTypeAlign(type, 0); copts.align_mode = save_align_mode; copts.oldalignment = save_oldalignment; if (type->type == TYPESTRUCT && !TYPE_STRUCT(type)->members && TYPE_STRUCT(type)->align > align) align = TYPE_STRUCT(type)->align; return align; } // TODO: investigate if this returns SInt16 actually SInt32 CMach_AllocationAlignment(Type *type, UInt32 qual) { SInt32 align; SInt32 qualalign; SInt32 argalign; SInt32 anotheralign; qualalign = CMach_GetQUALalign(qual); align = CMach_GetQualifiedTypeAlign(type, 1); if (qualalign > align) align = qualalign; argalign = CMach_ArgumentAlignment(type); if (argalign > align) align = argalign; switch (type->type) { case TYPEVOID: case TYPEMEMBERPOINTER: case TYPEPOINTER: anotheralign = 4; break; default: anotheralign = 1; } if (anotheralign > align) align = anotheralign; if (copts.optimizationlevel > 0) { if (type->type == TYPEARRAY || (type->type == TYPESTRUCT && (TYPE_STRUCT(type)->stype < STRUCT_TYPE_4 || TYPE_STRUCT(type)->stype > STRUCT_TYPE_E)) || type->type == TYPECLASS || (type->type == TYPEMEMBERPOINTER && (UInt32) type->size == 12)) { return (copts.some_alignment > align) ? copts.some_alignment : align; } } return align; } CInt64 CMach_CalcIntDiadic(Type *type, CInt64 left, short op, CInt64 right) { if (is_unsigned(type)) { switch (type->size) { case 1: CInt64_ConvertUInt8(&left); CInt64_ConvertUInt8(&right); break; case 2: CInt64_ConvertUInt16(&left); CInt64_ConvertUInt16(&right); break; case 4: CInt64_ConvertUInt32(&left); CInt64_ConvertUInt32(&right); break; case 8: break; default: CError_FATAL(327); } switch (op) { case '*': left = CInt64_MulU(left, right); break; case '/': if (CInt64_IsZero(&right)) CError_Warning(139); else left = CInt64_DivU(left, right); break; case '%': if (CInt64_IsZero(&right)) CError_Warning(139); else left = CInt64_ModU(left, right); break; case '+': left = CInt64_Add(left, right); break; case '-': left = CInt64_Sub(left, right); break; case TK_SHL: left = CInt64_Shl(left, right); break; case TK_SHR: left = CInt64_ShrU(left, right); break; case '<': CInt64_SetLong(&left, CInt64_LessU(left, right)); break; case '>': CInt64_SetLong(&left, CInt64_GreaterU(left, right)); break; case TK_LESS_EQUAL: CInt64_SetLong(&left, CInt64_LessEqualU(left, right)); break; case TK_GREATER_EQUAL: CInt64_SetLong(&left, CInt64_GreaterEqualU(left, right)); break; case TK_LOGICAL_EQ: CInt64_SetLong(&left, CInt64_Equal(left, right)); break; case TK_LOGICAL_NE: CInt64_SetLong(&left, CInt64_NotEqual(left, right)); break; case '&': left = CInt64_And(left, right); break; case '^': left = CInt64_Xor(left, right); break; case '|': left = CInt64_Or(left, right); break; case TK_LOGICAL_AND: CInt64_SetLong(&left, (CInt64_IsZero(&left) == 0 && CInt64_IsZero(&right) == 0)); break; case TK_LOGICAL_OR: CInt64_SetLong(&left, (CInt64_IsZero(&left) == 0 || CInt64_IsZero(&right) == 0)); break; default: CError_Error(120); } switch (type->size) { case 1: CInt64_ConvertUInt8(&left); break; case 2: CInt64_ConvertUInt16(&left); break; case 4: CInt64_ConvertUInt32(&left); break; case 8: break; } } else { switch (type->size) { case 1: CInt64_ConvertInt8(&left); CInt64_ConvertInt8(&right); break; case 2: CInt64_ConvertInt16(&left); CInt64_ConvertInt16(&right); break; case 4: CInt64_ConvertInt32(&left); CInt64_ConvertInt32(&right); break; case 8: break; default: CError_FATAL(389); } switch (op) { case '*': left = CInt64_Mul(left, right); break; case '/': if (CInt64_IsZero(&right)) CError_Warning(139); else left = CInt64_Div(left, right); break; case '%': if (CInt64_IsZero(&right)) CError_Warning(139); else left = CInt64_Mod(left, right); break; case '+': left = CInt64_Add(left, right); break; case '-': left = CInt64_Sub(left, right); break; case TK_SHL: left = CInt64_Shl(left, right); break; case TK_SHR: left = CInt64_Shr(left, right); break; case '<': CInt64_SetLong(&left, CInt64_Less(left, right)); break; case '>': CInt64_SetLong(&left, CInt64_Greater(left, right)); break; case TK_LESS_EQUAL: CInt64_SetLong(&left, CInt64_LessEqual(left, right)); break; case TK_GREATER_EQUAL: CInt64_SetLong(&left, CInt64_GreaterEqual(left, right)); break; case TK_LOGICAL_EQ: CInt64_SetLong(&left, CInt64_Equal(left, right)); break; case TK_LOGICAL_NE: CInt64_SetLong(&left, CInt64_NotEqual(left, right)); break; case '&': left = CInt64_And(left, right); break; case '^': left = CInt64_Xor(left, right); break; case '|': left = CInt64_Or(left, right); break; case TK_LOGICAL_AND: CInt64_SetLong(&left, (CInt64_IsZero(&left) == 0 && CInt64_IsZero(&right) == 0)); break; case TK_LOGICAL_OR: CInt64_SetLong(&left, (CInt64_IsZero(&left) == 0 || CInt64_IsZero(&right) == 0)); break; default: CError_Error(120); } switch (type->size) { case 1: CInt64_ConvertInt8(&left); break; case 2: CInt64_ConvertInt16(&left); break; case 4: CInt64_ConvertInt32(&left); break; case 8: break; } } return left; } CInt64 CMach_CalcIntMonadic(Type *type, short op, CInt64 val) { if (is_unsigned(type)) { switch (type->size) { case 1: CInt64_ConvertUInt8(&val); break; case 2: CInt64_ConvertUInt16(&val); break; case 4: CInt64_ConvertUInt32(&val); break; case 8: break; default: CError_FATAL(448); } switch (op) { case '-': val = CInt64_Neg(val); break; case '~': val = CInt64_Inv(val); break; case '!': val = CInt64_Not(val); break; default: CError_Error(120); } switch (type->size) { case 1: CInt64_ConvertUInt8(&val); break; case 2: CInt64_ConvertUInt16(&val); break; case 4: CInt64_ConvertUInt32(&val); break; case 8: break; } } else { switch (type->size) { case 1: CInt64_ConvertInt8(&val); break; case 2: CInt64_ConvertInt16(&val); break; case 4: CInt64_ConvertInt32(&val); break; case 8: break; default: CError_FATAL(478); } switch (op) { case '-': val = CInt64_Neg(val); break; case '~': val = CInt64_Inv(val); break; case '!': val = CInt64_Not(val); break; default: CError_Error(120); } switch (type->size) { case 1: CInt64_ConvertInt8(&val); break; case 2: CInt64_ConvertInt16(&val); break; case 4: CInt64_ConvertInt32(&val); break; case 8: break; } } return val; } CInt64 CMach_CalcIntConvertFromFloat(Type *type, Float fval) { CInt64 result; if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { if (is_unsigned(type)) CInt64_ConvertUFromLongDouble(&result, fval.value); else CInt64_ConvertFromLongDouble(&result, fval.value); } else { if (is_unsigned(type)) CInt64_SetULong(&result, fval.value); else CInt64_SetLong(&result, fval.value); } return result; } void CMach_InitIntMem(Type *type, CInt64 val, void *mem) { UInt32 lg; UInt16 sh; UInt8 ch; switch (type->type) { case TYPEINT: switch (type->size) { case 1: ch = (UInt8) CInt64_GetULong(&val); memcpy(mem, &ch, 1); break; case 2: sh = (UInt16) CTool_EndianConvertWord16(CInt64_GetULong(&val)); memcpy(mem, &sh, 2); break; case 4: lg = (UInt32) CTool_EndianConvertWord32(CInt64_GetULong(&val)); memcpy(mem, &lg, 4); break; case 8: CTool_EndianConvertWord64(val, mem); break; default: CError_FATAL(566); } break; default: CError_FATAL(570); } } void CMach_InitVectorMem(Type *type, MWVector128 val, void *mem, Boolean flag) { unsigned char uc[16]; unsigned short us[8]; unsigned int ul[4]; float f[4]; int i; switch (type->type) { case TYPESTRUCT: switch (TYPE_STRUCT(type)->stype) { case STRUCT_TYPE_4: case STRUCT_TYPE_5: case STRUCT_TYPE_6: for (i = 0; i < 16; i++) uc[i] = val.uc[i]; memcpy(mem, uc, 16); break; case STRUCT_TYPE_7: case STRUCT_TYPE_8: case STRUCT_TYPE_9: case STRUCT_TYPE_E: for (i = 0; i < 8; i++) us[i] = val.us[i]; memcpy(mem, us, 16); break; case STRUCT_TYPE_A: case STRUCT_TYPE_B: case STRUCT_TYPE_C: for (i = 0; i < 4; i++) ul[i] = val.ul[i]; memcpy(mem, ul, 16); break; case STRUCT_TYPE_D: for (i = 0; i < 4; i++) f[i] = val.f[i]; memcpy(mem, f, 16); break; default: CError_FATAL(655); } break; default: CError_FATAL(659); } } Float CMach_CalcFloatDiadic(Type *type, Float left, short op, Float right) { switch (op) { case '+': left.value += right.value; break; case '-': left.value -= right.value; break; case '*': left.value *= right.value; break; case '/': left.value /= right.value; break; default: CError_FATAL(679); } return CMach_CalcFloatConvert(type, left); } Float CMach_CalcFloatMonadic(Type *type, short op, Float fval) { if (op != '-') CError_FATAL(692); fval.value = -fval.value; return CMach_CalcFloatConvert(type, fval); } Boolean CMach_CalcFloatDiadicBool(Type *type, Float left, short op, Float right) { switch (op) { case TK_LOGICAL_EQ: return left.value == right.value; case TK_LOGICAL_NE: return left.value != right.value; case TK_LESS_EQUAL: return left.value <= right.value; case TK_GREATER_EQUAL: return left.value >= right.value; case '>': return left.value > right.value; case '<': return left.value < right.value; default: CError_FATAL(714); return 0; } } Boolean CMach_CalcVectorDiadicBool(Type *type, MWVector128 *left, short op, MWVector128 *right) { switch (op) { case TK_LOGICAL_EQ: return (left->ul[0] == right->ul[0]) && (left->ul[1] == right->ul[1]) && (left->ul[2] == right->ul[2]) && (left->ul[3] == right->ul[3]); case TK_LOGICAL_NE: return (left->ul[0] != right->ul[0]) && (left->ul[1] != right->ul[1]) && (left->ul[2] != right->ul[2]) && (left->ul[3] != right->ul[3]); default: CError_FATAL(740); return 0; } } char *CMach_FloatScan(char *input, Float *result, Boolean *fail) { double resultval; char *outpos; if (!(outpos = ScanFloat(input, &resultval, fail))) CError_ErrorTerm(154); if (*fail) result->value = 0.0; else result->value = resultval; return outpos; } Float CMach_CalcFloatConvertFromInt(Type *type, CInt64 val) { Float result; if ((type->type == TYPEINT || type->type == TYPEENUM) && (type->size == 8)) { if (is_unsigned(type)) result.value = CInt64_ConvertUToLongDouble(&val); else result.value = CInt64_ConvertToLongDouble(&val); } else { if (is_unsigned(type)) result.value = val.lo; else result.value = (SInt32) val.lo; } return result; } Float CMach_CalcFloatConvert(Type *type, Float fval) { switch (type->size) { case 4: fval.value = (float) fval.value; break; case 8: fval.value = (double) fval.value; break; case 10: case 12: break; default: CError_FATAL(801); } return fval; } Boolean CMach_FloatIsZero(Float fval) { return fval.value == 0.0; } Boolean CMach_FloatIsOne(Float fval) { return fval.value == 1.0; } Boolean CMach_FloatIsNegOne(Float fval) { return fval.value == -1.0; } void CMach_InitFloatMem(Type *type, Float val, void *mem) { float f; double d; if (type->type == TYPEFLOAT) { switch (type->size) { case 4: f = val.value; memcpy(mem, &f, 4); CTool_EndianConvertMem(mem, 4); return; case 8: d = val.value; memcpy(mem, &d, 8); CTool_EndianConvertMem(mem, 8); return; } } CError_FATAL(866); } void CMach_PrintFloat(char *buf, Float val) { double f; CMach_InitFloatMem((Type *) &stshortdouble, val, &f); sprintf(buf, "%g", f); } void CMach_PragmaParams() { if (copts.warn_illpragma) CError_Warning(186, 0); while (notendofline()) lex(); } void CMach_AdjustFuntionArgs() { // not called so we will never know what the args should have been :( } static SInt32 CMach_GetPPCTypeAlign(Type *type, Boolean flag1, Boolean flag2) { ClassList *base; ObjMemberVar *ivar; StructMember *member; SInt32 best; SInt32 ivarAlign; SInt32 qualAlign; SInt32 align = CMach_GetQualifiedTypeAlign(type, flag2); if (align <= 8) { while (type->type == TYPEARRAY) type = TYPE_POINTER(type)->target; if (flag1) { if (type->type == TYPEFLOAT && type->size > 4 && align < 8) return 8; } else if (align == 8) { if (type->type == TYPECLASS) { best = 4; for (base = TYPE_CLASS(type)->bases; base; base = base->next) { if (base->base->align > best) best = base->base->align; } for (ivar = TYPE_CLASS(type)->ivars; ivar; ivar = ivar->next) { ivarAlign = CMach_GetPPCTypeAlign(ivar->type, 0, flag2); if (ivarAlign > best) best = ivarAlign; if (flag2) { qualAlign = CMach_GetQUALalign(ivar->qual); if (qualAlign > best) best = qualAlign; } } return best; } if (type->type == TYPESTRUCT) { best = 4; for (member = TYPE_STRUCT(type)->members; member; member = member->next) { ivarAlign = CMach_GetPPCTypeAlign(member->type, 0, flag2); if (ivarAlign > best) best = ivarAlign; if (flag2) { qualAlign = CMach_GetQUALalign(member->qual); if (qualAlign > best) best = qualAlign; } } return best; } } } return align; } static SInt16 CMach_GetQualifiedStructAlign(TypeStruct *tstruct, Boolean flag) { StructMember *member; SInt32 best; SInt32 align; Boolean isFirst; // very close to matching but tstruct->stype gets cached when it should not be if (tstruct->stype >= STRUCT_TYPE_4 && tstruct->stype <= STRUCT_TYPE_E) { return 16; } else { switch (copts.align_mode) { case AlignMode3_1Byte: case AlignMode8_Packed: return 1; case AlignMode0_Mac68k: return 2; case AlignMode1_Mac68k4byte: return (tstruct->size <= 2) ? 2 : 4; } if (tstruct->size <= 1) return 1; best = 1; switch (copts.align_mode) { default: CError_FATAL(1026); case AlignMode4_2Byte: case AlignMode5_4Byte: case AlignMode6_8Byte: case AlignMode7_16Byte: for (member = tstruct->members; member; member = member->next) { align = CMach_GetQualifiedTypeAlign(member->type, flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(member->qual); if (align > best) best = align; } } return best; case AlignMode2_PPC: if (copts.oldalignment) { for (member = tstruct->members; member; member = member->next) { align = CMach_GetQualifiedTypeAlign(member->type, flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(member->qual); if (align > best) best = align; } } } else if (tstruct->stype == STRUCT_TYPE_UNION) { for (member = tstruct->members; member; member = member->next) { align = CMach_GetPPCTypeAlign(member->type, 1, flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(member->qual); if (align > best) best = align; } } } else { isFirst = 1; for (member = tstruct->members; member; member = member->next) { align = CMach_GetPPCTypeAlign(member->type, isFirst || (best >= 8), flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(member->qual); if (align > best) best = align; } isFirst = 0; } } return best; } } } SInt16 CMach_GetStructAlign(TypeStruct *tstruct) { return CMach_GetQualifiedStructAlign(tstruct, 1); } static SInt16 CMach_GetQualifiedClassAlign(TypeClass *tclass, Boolean flag) { ClassList *base; ObjMemberVar *ivar; SInt32 best; SInt32 align; Boolean isFirst; switch (copts.align_mode) { case AlignMode3_1Byte: case AlignMode8_Packed: return 1; case AlignMode0_Mac68k: return 2; case AlignMode1_Mac68k4byte: return (tclass->size <= 2) ? 2 : 4; } if (tclass->size <= 1) return 1; best = 1; switch (copts.align_mode) { default: CError_FATAL(1149); case AlignMode4_2Byte: case AlignMode5_4Byte: case AlignMode6_8Byte: case AlignMode7_16Byte: for (base = tclass->bases; base; base = base->next) { if ((align = base->base->align) > best) best = align; } for (ivar = tclass->ivars; ivar; ivar = ivar->next) { align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); if (align > best) best = align; } return best; case AlignMode2_PPC: best = 1; if (copts.oldalignment) { for (base = tclass->bases; base; base = base->next) { if ((align = base->base->align) > best) best = align; } for (ivar = tclass->ivars; ivar; ivar = ivar->next) { align = CMach_GetMemberAlignment(ivar->type, flag ? CMach_GetQUALalign(ivar->qual) : 0, flag); if (align > best) best = align; } } else { isFirst = 1; for (base = tclass->bases; base; base = base->next) { if ((align = base->base->align) > best) best = align; isFirst = 0; } if (tclass->mode == 1) { for (ivar = tclass->ivars; ivar; ivar = ivar->next) { align = CMach_GetPPCTypeAlign(ivar->type, 1, flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(ivar->qual); if (align > best) best = align; } } } else { for (ivar = tclass->ivars; ivar; ivar = ivar->next) { if (ivar->offset && align != 8) isFirst = 0; align = CMach_GetPPCTypeAlign(ivar->type, isFirst || (best >= 8), flag); if (align > best) best = align; if (flag) { align = CMach_GetQUALalign(ivar->qual); if (align > best) best = align; } } } } return best; } } SInt16 CMach_GetClassAlign(TypeClass *tclass) { return CMach_GetQualifiedClassAlign(tclass, 1); } static SInt16 CMach_GetWinTypeAlign(Type *type) { int packoffs = copts.align_mode - 3; SInt32 align = cmach_packsize[packoffs]; if (type->size < align) align = type->size; return align; } static SInt16 CMach_GetWinMinimizeAlign(SInt16 align) { int packoffs = copts.align_mode - 3; SInt16 minimum = cmach_packsize[packoffs]; if (minimum < align) align = minimum; return align; } static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) { Boolean r31; SInt16 align; if (type->type == TYPESTRUCT && TYPE_STRUCT(type)->stype >= STRUCT_TYPE_4 && TYPE_STRUCT(type)->stype <= STRUCT_TYPE_E) return 16; switch (copts.align_mode) { case AlignMode3_1Byte: case AlignMode8_Packed: return 1; case AlignMode4_2Byte: case AlignMode5_4Byte: case AlignMode6_8Byte: case AlignMode7_16Byte: r31 = 1; break; default: r31 = 0; break; } restart: switch (type->type) { case TYPEVOID: return 0; case TYPEFUNC: return 0; case TYPEENUM: type = TYPE_ENUM(type)->enumtype; case TYPEINT: if (r31) return CMach_GetWinTypeAlign(type); if (type->size == 1) return 1; if (copts.oldalignment && type->size == 8) return 8; if (copts.align_mode != AlignMode0_Mac68k && type->size >= 4) return 4; return 2; case TYPEFLOAT: if (r31) return CMach_GetWinTypeAlign(type); switch (copts.align_mode) { case AlignMode0_Mac68k: return 2; case AlignMode1_Mac68k4byte: return 4; case AlignMode2_PPC: if (copts.oldalignment && type->size > 4) return 8; return 4; default: CError_FATAL(1346); } case TYPEMEMBERPOINTER: case TYPEPOINTER: if (r31) return CMach_GetWinTypeAlign(type); if (copts.align_mode == AlignMode0_Mac68k) return 2; else return 4; case TYPEARRAY: if (copts.align_array_members) { if (r31) return CMach_GetWinTypeAlign(type); if (type->size == 1) return 1; if (copts.align_mode == AlignMode0_Mac68k || type->size <= 2) return 2; if (copts.align_mode == AlignMode1_Mac68k4byte || type->size < 8) return 4; align = CMach_GetQualifiedTypeAlign(TYPE_POINTER(type)->target, flag); if (align > 4) return align; else return 4; } else { type = TYPE_POINTER(type)->target; goto restart; } case TYPESTRUCT: if (flag) align = TYPE_STRUCT(type)->align; else align = CMach_GetQualifiedStructAlign(TYPE_STRUCT(type), flag); if (r31) return CMach_GetWinMinimizeAlign(align); else return align; case TYPECLASS: if (flag) align = TYPE_CLASS(type)->align; else align = CMach_GetQualifiedClassAlign(TYPE_CLASS(type), flag); if (r31) return CMach_GetWinMinimizeAlign(align); else return align; case TYPEBITFIELD: type = TYPE_BITFIELD(type)->bitfieldtype; goto restart; case TYPETEMPLATE: return 1; default: CError_FATAL(1392); return 0; } } SInt16 CMach_GetTypeAlign(Type *type) { return CMach_GetQualifiedTypeAlign(type, 1); } static SInt16 CMach_GetMemberAlignment(Type *type, SInt32 var, Boolean flag) { SInt32 align; align = CMach_GetQualifiedTypeAlign(type, flag); if (align < 1) align = 1; if (type->type == TYPESTRUCT && TYPE_STRUCT(type)->stype >= STRUCT_TYPE_4 && TYPE_STRUCT(type)->stype <= STRUCT_TYPE_E && align < 16) align = 16; switch (copts.align_mode) { case AlignMode8_Packed: align = 1; break; case AlignMode0_Mac68k: if (align > 2) align = 2; break; case AlignMode1_Mac68k4byte: if (align > 4) align = 4; break; case AlignMode2_PPC: if (!copts.oldalignment) align = CMach_GetPPCTypeAlign(type, !cmach_structoffset || (cmach_structalign >= 8), flag); if (var > align) align = var; break; } if (align > cmach_structalign) cmach_structalign = align; return align; } SInt16 CMach_MemberAlignValue(Type *type, SInt32 var) { SInt16 align = CMach_GetMemberAlignment(type, 0, 1); if (align <= 1) return 0; return (align - 1) & (align - (var & (align - 1))); } static SInt16 MemberAlignValue(Type *type, SInt32 var1, SInt32 var2) { SInt16 align = CMach_GetMemberAlignment(type, var2, 1); return (align - 1) & (align - (var1 & (align - 1))); } void CMach_StructLayoutInitOffset(SInt32 offset) { cmach_structoffset = offset; cmach_structalign = 4; cmach_curbfsize = 0; } SInt32 CMach_StructLayoutGetCurSize() { return cmach_structoffset; } SInt32 CMach_StructLayoutGetOffset(Type *type, UInt32 qual) { SInt32 align; SInt32 offset; qual = CParser_GetTypeQualifiers(type, qual); cmach_curbfsize = 0; align = MemberAlignValue(type, cmach_structoffset, CMach_GetQUALalign(qual)); offset = cmach_structoffset + align; cmach_structoffset = offset + type->size; return offset; } SInt32 CMach_StructLayoutBitfield(TypeBitfield *tbitfield, UInt32 qual) { SInt16 align; SInt16 padding_at_start; SInt16 basesize; SInt16 basesize_bits; SInt16 required_alignment; SInt16 r4; padding_at_start = 0; required_alignment = 0; align = CMach_GetQUALalign(qual); if (align <= tbitfield->bitfieldtype->size) align = 0; switch (tbitfield->bitfieldtype->size) { case 1: basesize = 1; basesize_bits = 8; required_alignment = 0; break; case 2: basesize = 2; basesize_bits = 16; required_alignment = 2; break; case 4: if (copts.align_mode != AlignMode0_Mac68k && copts.align_mode != AlignMode4_2Byte) required_alignment = 4; else required_alignment = 2; basesize = 4; basesize_bits = 32; break; default: CError_FATAL(1620); } switch (copts.align_mode) { case AlignMode3_1Byte: case AlignMode8_Packed: required_alignment = 0; break; } r4 = required_alignment; if (align > required_alignment) r4 = align; if (r4 && (cmach_structoffset & (r4 - 1))) padding_at_start = r4 - (cmach_structoffset & (r4 - 1)); if (!cmach_curbfsize) { cmach_structoffset += padding_at_start; if (!tbitfield->unkB) return cmach_structoffset; cmach_curbfsize = tbitfield->unkB; cmach_curbfbasesize = basesize; cmach_curbfoffset = cmach_structoffset; cmach_structoffset += basesize; tbitfield->unkA = 0; return cmach_curbfoffset; } else { if (!tbitfield->unkB || (cmach_curbfsize + tbitfield->unkB) > basesize_bits || cmach_curbfbasesize != basesize) { cmach_structoffset += padding_at_start; cmach_curbfsize = 0; cmach_curbfbasesize = basesize; if (!tbitfield->unkB) return cmach_structoffset; cmach_curbfoffset = cmach_structoffset; cmach_structoffset += basesize; } tbitfield->unkA = cmach_curbfsize; cmach_curbfsize += tbitfield->unkB; return cmach_curbfoffset; } } static Boolean CMach_IsTrivialClass(TypeClass *tclass) { return !CClass_Constructor(tclass); } UInt8 CMach_GetFunctionResultClass(TypeFunc *tfunc) { switch (tfunc->functype->type) { case TYPESTRUCT: if (tfunc->functype->type == TYPESTRUCT && TYPE_STRUCT(tfunc->functype)->stype >= STRUCT_TYPE_4 && TYPE_STRUCT(tfunc->functype)->stype <= STRUCT_TYPE_E) return 0; case TYPECLASS: case TYPEMEMBERPOINTER: return CMach_PassResultInHiddenArg(tfunc->functype) ? 1 : 0; default: return 0; } } Boolean CMach_PassResultInHiddenArg(Type *type) { switch (type->type) { case TYPESTRUCT: if (TYPE_STRUCT(type)->stype >= STRUCT_TYPE_4 && TYPE_STRUCT(type)->stype <= STRUCT_TYPE_E) return 0; else return 1; case TYPECLASS: return 1; case TYPEMEMBERPOINTER: return (type->size == 4) ? 0 : 1; default: return 0; } } char *CMach_GetCPU() { switch (copts.cpu) { case CPU_PPC401: return "__PPC401__"; case CPU_PPC403: return "__PPC403__"; case CPU_PPC505: return "__PPC505__"; case CPU_PPC509: return "__PPC509__"; case CPU_PPC555: return "__PPC555__"; case CPU_PPC556: return "__PPC556__"; case CPU_PPC565: return "__PPC565__"; case CPU_PPC601: return "__PPC601__"; case CPU_PPC602: return "__PPC602__"; case CPU_PPC603: return "__PPC603__"; case CPU_PPC603e: return "__PPC603e__"; case CPU_PPC604: return "__PPC604__"; case CPU_PPC604e: return "__PPC604e__"; case CPU_PPC740: return "__PPC740__"; case CPU_PPC750: return "__PPC750__"; case CPU_PPC801: return "__PPC801__"; case CPU_PPC821: return "__PPC821__"; case CPU_PPC823: return "__PPC823__"; case CPU_PPC850: return "__PPC850__"; case CPU_PPC860: return "__PPC860__"; case CPU_PPC7400: return "__PPC7400__"; case CPU_PPC7450: return "__PPC7450__"; case CPU_PPC8240: return "__PPC8240__"; case CPU_PPC8260: return "__PPC8260__"; case CPU_PPCGEKKO: return "__PPCGEKKO__"; case CPU_PPCELF: return "__PPCELF__"; default: return NULL; } } Boolean CMach_FloatIsPowerOf2(Float flt) { return (flt.value == 2.0) || (flt.value == 4.0) || (flt.value == 8.0) || (flt.value == 16.0) || (flt.value == 32.0) || (flt.value == 64.0) || (flt.value == 128.0) || (flt.value == 256.0) || (flt.value == 512.0) || (flt.value == 1024.0); } Float CMach_FloatReciprocal(Float flt) { flt.value = 1.0 / flt.value; return flt; } SInt32 CMach_RoundedSizeOf(Object *object) { SInt32 size = object->type->size; SInt32 align = CMach_GetTypeAlign(object->type) - 1; return (size + align) & ~align; } void CMach_ReInitRuntimeObjects() { HashNameNode *e0 = GetHashNameNodeExport("[0]"); HashNameNode *e1 = GetHashNameNodeExport("[1]"); HashNameNode *e2 = GetHashNameNodeExport("[2]"); HashNameNode *e3 = GetHashNameNodeExport("[3]"); HashNameNode *e4 = GetHashNameNodeExport("[4]"); HashNameNode *e5 = GetHashNameNodeExport("[5]"); HashNameNode *e6 = GetHashNameNodeExport("[6]"); HashNameNode *e7 = GetHashNameNodeExport("[7]"); HashNameNode *e8 = GetHashNameNodeExport("[8]"); HashNameNode *e9 = GetHashNameNodeExport("[9]"); HashNameNode *e10 = GetHashNameNodeExport("[10]"); HashNameNode *e11 = GetHashNameNodeExport("[11]"); HashNameNode *e12 = GetHashNameNodeExport("[12]"); HashNameNode *e13 = GetHashNameNodeExport("[13]"); HashNameNode *e14 = GetHashNameNodeExport("[14]"); HashNameNode *e15 = GetHashNameNodeExport("[15]"); HashNameNode *vuc = GetHashNameNodeExport("vector unsigned char"); HashNameNode *vus = GetHashNameNodeExport("vector unsigned short"); HashNameNode *vui = GetHashNameNodeExport("vector unsigned int"); HashNameNode *vsc = GetHashNameNodeExport("vector signed char"); HashNameNode *vss = GetHashNameNodeExport("vector signed short"); HashNameNode *vsi = GetHashNameNodeExport("vector signed int"); HashNameNode *vbc = GetHashNameNodeExport("vector bool char"); HashNameNode *vbs = GetHashNameNodeExport("vector bool short"); HashNameNode *vbi = GetHashNameNodeExport("vector bool int"); HashNameNode *vf = GetHashNameNodeExport("vector float"); HashNameNode *vp = GetHashNameNodeExport("vector pixel"); stvectorunsignedchar.name = vuc; stvectorunsignedshort.name = vus; stvectorunsignedlong.name = vui; stvectorsignedchar.name = vsc; stvectorsignedshort.name = vss; stvectorsignedlong.name = vsi; stvectorboolchar.name = vbc; stvectorboolshort.name = vbs; stvectorboollong.name = vbi; stvectorfloat.name = vf; stvectorpixel.name = vp; stVUC_unsignedchar0.name = e0; stVUC_unsignedchar1.name = e1; stVUC_unsignedchar2.name = e2; stVUC_unsignedchar3.name = e3; stVUC_unsignedchar4.name = e4; stVUC_unsignedchar5.name = e5; stVUC_unsignedchar6.name = e6; stVUC_unsignedchar7.name = e7; stVUC_unsignedchar8.name = e8; stVUC_unsignedchar9.name = e9; stVUC_unsignedchar10.name = e10; stVUC_unsignedchar11.name = e11; stVUC_unsignedchar12.name = e12; stVUC_unsignedchar13.name = e13; stVUC_unsignedchar14.name = e14; stVUC_unsignedchar15.name = e15; stVSC_signedchar0.name = e0; stVSC_signedchar1.name = e1; stVSC_signedchar2.name = e2; stVSC_signedchar3.name = e3; stVSC_signedchar4.name = e4; stVSC_signedchar5.name = e5; stVSC_signedchar6.name = e6; stVSC_signedchar7.name = e7; stVSC_signedchar8.name = e8; stVSC_signedchar9.name = e9; stVSC_signedchar10.name = e10; stVSC_signedchar11.name = e11; stVSC_signedchar12.name = e12; stVSC_signedchar13.name = e13; stVSC_signedchar14.name = e14; stVSC_signedchar15.name = e15; stVUS_unsignedshort0.name = e0; stVUS_unsignedshort1.name = e1; stVUS_unsignedshort2.name = e2; stVUS_unsignedshort3.name = e3; stVUS_unsignedshort4.name = e4; stVUS_unsignedshort5.name = e5; stVUS_unsignedshort6.name = e6; stVUS_unsignedshort7.name = e7; stVSS_signedshort0.name = e0; stVSS_signedshort1.name = e1; stVSS_signedshort2.name = e2; stVSS_signedshort3.name = e3; stVSS_signedshort4.name = e4; stVSS_signedshort5.name = e5; stVSS_signedshort6.name = e6; stVSS_signedshort7.name = e7; stVUL_unsignedlong0.name = e0; stVUL_unsignedlong1.name = e1; stVUL_unsignedlong2.name = e2; stVUL_unsignedlong3.name = e3; stVSL_signedlong0.name = e0; stVSL_signedlong1.name = e1; stVSL_signedlong2.name = e2; stVSL_signedlong3.name = e3; stVF_float0.name = e0; stVF_float1.name = e1; stVF_float2.name = e2; stVF_float3.name = e3; }