mirror of https://git.wuffs.org/MWCC
1485 lines
50 KiB
C
1485 lines
50 KiB
C
#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/ScanFloat.h"
|
|
#include "compiler/objects.h"
|
|
#include "compiler/types.h"
|
|
|
|
TypeIntegral stbool = {TYPEINT, 1, IT_BOOL};
|
|
TypeIntegral stchar = {TYPEINT, 1, IT_CHAR};
|
|
TypeIntegral stsignedchar = {TYPEINT, 1, IT_SCHAR};
|
|
TypeIntegral stunsignedchar = {TYPEINT, 1, 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 = {TYPEFLOAT, 8, IT_SHORTDOUBLE};
|
|
TypeIntegral stdouble = {TYPEFLOAT, 8, IT_DOUBLE};
|
|
TypeIntegral stlongdouble = {TYPEFLOAT, 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(void) {
|
|
}
|
|
|
|
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) {
|
|
char save_align_mode;
|
|
UInt8 save_oldalignment;
|
|
SInt32 align;
|
|
|
|
save_align_mode = copts.structalignment;
|
|
save_oldalignment = copts.oldalignment;
|
|
copts.structalignment = AlignMode2_PPC;
|
|
copts.oldalignment = 0;
|
|
align = CMach_GetQualifiedTypeAlign(type, 0);
|
|
copts.structalignment = 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.min_struct_alignment > align) ? copts.min_struct_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(CErrorStr139);
|
|
else
|
|
left = CInt64_DivU(left, right);
|
|
break;
|
|
case '%':
|
|
if (CInt64_IsZero(&right))
|
|
CError_Warning(CErrorStr139);
|
|
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) && !CInt64_IsZero(&right)));
|
|
break;
|
|
case TK_LOGICAL_OR:
|
|
CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right)));
|
|
break;
|
|
default:
|
|
CError_Error(CErrorStr120);
|
|
}
|
|
|
|
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(CErrorStr139);
|
|
else
|
|
left = CInt64_Div(left, right);
|
|
break;
|
|
case '%':
|
|
if (CInt64_IsZero(&right))
|
|
CError_Warning(CErrorStr139);
|
|
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) && !CInt64_IsZero(&right)));
|
|
break;
|
|
case TK_LOGICAL_OR:
|
|
CInt64_SetLong(&left, (!CInt64_IsZero(&left) || !CInt64_IsZero(&right)));
|
|
break;
|
|
default:
|
|
CError_Error(CErrorStr120);
|
|
}
|
|
|
|
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(CErrorStr120);
|
|
}
|
|
|
|
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(CErrorStr120);
|
|
}
|
|
|
|
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(CErrorStr154);
|
|
|
|
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(void) {
|
|
if (copts.warn_illpragma)
|
|
CError_Warning(CErrorStr186, 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(const TypeStruct *tstruct, Boolean flag) {
|
|
StructMember *member;
|
|
SInt32 best;
|
|
SInt32 align;
|
|
Boolean isFirst;
|
|
|
|
if (tstruct->stype >= STRUCT_TYPE_4 && tstruct->stype <= STRUCT_TYPE_E)
|
|
return 16;
|
|
|
|
switch (copts.structalignment) {
|
|
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.structalignment) {
|
|
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 (TYPE_STRUCT(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.structalignment) {
|
|
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.structalignment) {
|
|
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.structalignment - 3;
|
|
SInt32 align = cmach_packsize[packoffs];
|
|
if (type->size < align)
|
|
align = type->size;
|
|
return align;
|
|
}
|
|
|
|
static SInt16 CMach_GetWinMinimizeAlign(SInt16 align) {
|
|
int packoffs = copts.structalignment - 3;
|
|
SInt16 minimum = cmach_packsize[packoffs];
|
|
if (minimum < align)
|
|
align = minimum;
|
|
return align;
|
|
}
|
|
|
|
static SInt16 CMach_GetQualifiedTypeAlign(Type *type, Boolean flag) {
|
|
Boolean isWin;
|
|
SInt16 align;
|
|
|
|
if (type->type == TYPESTRUCT && TYPE_STRUCT(type)->stype >= STRUCT_TYPE_4 && TYPE_STRUCT(type)->stype <= STRUCT_TYPE_E)
|
|
return 16;
|
|
|
|
switch (copts.structalignment) {
|
|
case AlignMode3_1Byte:
|
|
case AlignMode8_Packed:
|
|
return 1;
|
|
case AlignMode4_2Byte:
|
|
case AlignMode5_4Byte:
|
|
case AlignMode6_8Byte:
|
|
case AlignMode7_16Byte:
|
|
isWin = 1;
|
|
break;
|
|
default:
|
|
isWin = 0;
|
|
break;
|
|
}
|
|
|
|
restart:
|
|
switch (type->type) {
|
|
case TYPEVOID:
|
|
return 0;
|
|
case TYPEFUNC:
|
|
return 0;
|
|
case TYPEENUM:
|
|
type = TYPE_ENUM(type)->enumtype;
|
|
case TYPEINT:
|
|
if (isWin)
|
|
return CMach_GetWinTypeAlign(type);
|
|
if (type->size == 1)
|
|
return 1;
|
|
if (copts.oldalignment && type->size == 8)
|
|
return 8;
|
|
if (copts.structalignment != AlignMode0_Mac68k && type->size >= 4)
|
|
return 4;
|
|
return 2;
|
|
case TYPEFLOAT:
|
|
if (isWin)
|
|
return CMach_GetWinTypeAlign(type);
|
|
switch (copts.structalignment) {
|
|
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 (isWin)
|
|
return CMach_GetWinTypeAlign(type);
|
|
if (copts.structalignment == AlignMode0_Mac68k)
|
|
return 2;
|
|
else
|
|
return 4;
|
|
case TYPEARRAY:
|
|
if (copts.alignarraymembers) {
|
|
if (isWin)
|
|
return CMach_GetWinTypeAlign(type);
|
|
if (type->size == 1)
|
|
return 1;
|
|
if (copts.structalignment == AlignMode0_Mac68k || type->size <= 2)
|
|
return 2;
|
|
if (copts.structalignment == 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 (isWin)
|
|
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 (isWin)
|
|
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 (IS_TYPE_VECTOR(type) && align < 16)
|
|
align = 16;
|
|
|
|
switch (copts.structalignment) {
|
|
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(void) {
|
|
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.structalignment != AlignMode0_Mac68k && copts.structalignment != AlignMode4_2Byte)
|
|
required_alignment = 4;
|
|
else
|
|
required_alignment = 2;
|
|
basesize = 4;
|
|
basesize_bits = 32;
|
|
break;
|
|
default:
|
|
CError_FATAL(1620);
|
|
}
|
|
|
|
switch (copts.structalignment) {
|
|
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(void) {
|
|
switch (copts.processor) {
|
|
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(void) {
|
|
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;
|
|
}
|