X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Ftgsi%2Ftgsi_exec.c;h=b7569e74d4b6986ddf172eccdfbb707cb229f2e8;hb=48302e9b309c7ce218de2e522c91bdc87e61cdbc;hp=5af0a947947fed528ed5553bd76c2230c22c7ade;hpb=1f713059934c2365a42aadfdca49213b36a7de90;p=mesa.git diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 5af0a947947..b7569e74d4b 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -62,6 +62,9 @@ #define FAST_MATH 1 +/** for tgsi_full_instruction::Flags */ +#define SOA_DEPENDENCY_FLAG 0x1 + #define TILE_TOP_LEFT 0 #define TILE_TOP_RIGHT 1 #define TILE_BOTTOM_LEFT 2 @@ -104,6 +107,7 @@ #define TEMP_HALF_I TGSI_EXEC_TEMP_HALF_I #define TEMP_HALF_C TGSI_EXEC_TEMP_HALF_C #define TEMP_R0 TGSI_EXEC_TEMP_R0 +#define TEMP_P0 TGSI_EXEC_TEMP_P0 #define IS_CHANNEL_ENABLED(INST, CHAN)\ ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN))) @@ -182,7 +186,7 @@ print_temp(const struct tgsi_exec_machine *mach, uint index) * MOV t3, t2; * The second instruction will have the wrong value for t0 if executed as-is. */ -static boolean +boolean tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst) { uint i, chan; @@ -207,9 +211,8 @@ tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst) uint channelsWritten = 0x0; FOR_EACH_ENABLED_CHANNEL(*inst, chan) { /* check if we're reading a channel that's been written */ - uint swizzle = tgsi_util_get_full_src_register_extswizzle(&inst->FullSrcRegisters[i], chan); - if (swizzle <= TGSI_SWIZZLE_W && - (channelsWritten & (1 << swizzle))) { + uint swizzle = tgsi_util_get_full_src_register_swizzle(&inst->FullSrcRegisters[i], chan); + if (channelsWritten & (1 << swizzle)) { return TRUE; } @@ -328,19 +331,24 @@ tgsi_exec_machine_bind_shader( * sizeof(struct tgsi_full_instruction)); maxInstructions += 10; } - memcpy(instructions + numInstructions, - &parse.FullToken.FullInstruction, - sizeof(instructions[0])); -#if 0 if (tgsi_check_soa_dependencies(&parse.FullToken.FullInstruction)) { - debug_printf("SOA dependency in instruction:\n"); - tgsi_dump_instruction(&parse.FullToken.FullInstruction, - numInstructions); + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + parse.FullToken.FullInstruction.Flags = SOA_DEPENDENCY_FLAG; + /* XXX we only handle SOA dependencies properly for MOV/SWZ + * at this time! + */ + if (opcode != TGSI_OPCODE_MOV) { + debug_printf("Warning: SOA dependency in instruction" + " is not handled:\n"); + tgsi_dump_instruction(&parse.FullToken.FullInstruction, + numInstructions); + } } -#else - (void) tgsi_check_soa_dependencies; -#endif + + memcpy(instructions + numInstructions, + &parse.FullToken.FullInstruction, + sizeof(instructions[0])); numInstructions++; break; @@ -375,15 +383,9 @@ tgsi_exec_machine_create( void ) if (!mach) goto fail; - mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; + memset(mach, 0, sizeof(*mach)); - mach->Samplers = NULL; - mach->Consts = NULL; - mach->Tokens = NULL; - mach->Primitives = NULL; - mach->InterpCoefs = NULL; - mach->Instructions = NULL; - mach->Declarations = NULL; + mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; /* Setup constants. */ for( i = 0; i < 4; i++ ) { @@ -1128,10 +1130,10 @@ fetch_src_file_channel( union tgsi_exec_channel *chan ) { switch( swizzle ) { - case TGSI_EXTSWIZZLE_X: - case TGSI_EXTSWIZZLE_Y: - case TGSI_EXTSWIZZLE_Z: - case TGSI_EXTSWIZZLE_W: + case TGSI_SWIZZLE_X: + case TGSI_SWIZZLE_Y: + case TGSI_SWIZZLE_Z: + case TGSI_SWIZZLE_W: switch( file ) { case TGSI_FILE_CONSTANT: assert(mach->Consts); @@ -1186,6 +1188,17 @@ fetch_src_file_channel( chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3]; break; + case TGSI_FILE_PREDICATE: + assert(index->i[0] < TGSI_EXEC_NUM_PREDS); + assert(index->i[1] < TGSI_EXEC_NUM_PREDS); + assert(index->i[2] < TGSI_EXEC_NUM_PREDS); + assert(index->i[3] < TGSI_EXEC_NUM_PREDS); + chan->u[0] = mach->Addrs[0].xyzw[swizzle].u[0]; + chan->u[1] = mach->Addrs[0].xyzw[swizzle].u[1]; + chan->u[2] = mach->Addrs[0].xyzw[swizzle].u[2]; + chan->u[3] = mach->Addrs[0].xyzw[swizzle].u[3]; + break; + case TGSI_FILE_OUTPUT: /* vertex/fragment output vars can be read too */ chan->u[0] = mach->Outputs[index->i[0]].xyzw[swizzle].u[0]; @@ -1199,14 +1212,6 @@ fetch_src_file_channel( } break; - case TGSI_EXTSWIZZLE_ZERO: - *chan = mach->Temps[TEMP_0_I].xyzw[TEMP_0_C]; - break; - - case TGSI_EXTSWIZZLE_ONE: - *chan = mach->Temps[TEMP_1_I].xyzw[TEMP_1_C]; - break; - default: assert( 0 ); } @@ -1365,7 +1370,7 @@ fetch_source( */ } - swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index ); + swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); fetch_src_file_channel( mach, reg->SrcRegister.File, @@ -1473,119 +1478,17 @@ store_dest( dst = &mach->Addrs[index].xyzw[chan_index]; break; + case TGSI_FILE_PREDICATE: + index = reg->DstRegister.Index; + assert(index < TGSI_EXEC_NUM_PREDS); + dst = &mach->Addrs[index].xyzw[chan_index]; + break; + default: assert( 0 ); return; } - if (inst->InstructionExtNv.CondFlowEnable) { - union tgsi_exec_channel *cc = &mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C]; - uint swizzle; - uint shift; - uint mask; - uint test; - - /* Only CC0 supported. - */ - assert( inst->InstructionExtNv.CondFlowIndex < 1 ); - - switch (chan_index) { - case CHAN_X: - swizzle = inst->InstructionExtNv.CondSwizzleX; - break; - case CHAN_Y: - swizzle = inst->InstructionExtNv.CondSwizzleY; - break; - case CHAN_Z: - swizzle = inst->InstructionExtNv.CondSwizzleZ; - break; - case CHAN_W: - swizzle = inst->InstructionExtNv.CondSwizzleW; - break; - default: - assert( 0 ); - return; - } - - switch (swizzle) { - case TGSI_SWIZZLE_X: - shift = TGSI_EXEC_CC_X_SHIFT; - mask = TGSI_EXEC_CC_X_MASK; - break; - case TGSI_SWIZZLE_Y: - shift = TGSI_EXEC_CC_Y_SHIFT; - mask = TGSI_EXEC_CC_Y_MASK; - break; - case TGSI_SWIZZLE_Z: - shift = TGSI_EXEC_CC_Z_SHIFT; - mask = TGSI_EXEC_CC_Z_MASK; - break; - case TGSI_SWIZZLE_W: - shift = TGSI_EXEC_CC_W_SHIFT; - mask = TGSI_EXEC_CC_W_MASK; - break; - default: - assert( 0 ); - return; - } - - switch (inst->InstructionExtNv.CondMask) { - case TGSI_CC_GT: - test = ~(TGSI_EXEC_CC_GT << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_EQ: - test = ~(TGSI_EXEC_CC_EQ << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_LT: - test = ~(TGSI_EXEC_CC_LT << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_GE: - test = ~((TGSI_EXEC_CC_GT | TGSI_EXEC_CC_EQ) << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_LE: - test = ~((TGSI_EXEC_CC_LT | TGSI_EXEC_CC_EQ) << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_NE: - test = ~((TGSI_EXEC_CC_GT | TGSI_EXEC_CC_LT | TGSI_EXEC_CC_UN) << shift) & mask; - for (i = 0; i < QUAD_SIZE; i++) - if (cc->u[i] & test) - execmask &= ~(1 << i); - break; - - case TGSI_CC_TR: - break; - - case TGSI_CC_FL: - for (i = 0; i < QUAD_SIZE; i++) - execmask &= ~(1 << i); - break; - - default: - assert( 0 ); - return; - } - } - switch (inst->Instruction.Saturate) { case TGSI_SAT_NONE: for (i = 0; i < QUAD_SIZE; i++) @@ -1620,51 +1523,6 @@ store_dest( default: assert( 0 ); } - - if (inst->InstructionExtNv.CondDstUpdate) { - union tgsi_exec_channel *cc = &mach->Temps[TEMP_CC_I].xyzw[TEMP_CC_C]; - uint shift; - uint mask; - - /* Only CC0 supported. - */ - assert( inst->InstructionExtNv.CondDstIndex < 1 ); - - switch (chan_index) { - case CHAN_X: - shift = TGSI_EXEC_CC_X_SHIFT; - mask = ~TGSI_EXEC_CC_X_MASK; - break; - case CHAN_Y: - shift = TGSI_EXEC_CC_Y_SHIFT; - mask = ~TGSI_EXEC_CC_Y_MASK; - break; - case CHAN_Z: - shift = TGSI_EXEC_CC_Z_SHIFT; - mask = ~TGSI_EXEC_CC_Z_MASK; - break; - case CHAN_W: - shift = TGSI_EXEC_CC_W_SHIFT; - mask = ~TGSI_EXEC_CC_W_MASK; - break; - default: - assert( 0 ); - return; - } - - for (i = 0; i < QUAD_SIZE; i++) - if (execmask & (1 << i)) { - cc->u[i] &= mask; - if (dst->f[i] < 0.0f) - cc->u[i] |= TGSI_EXEC_CC_LT << shift; - else if (dst->f[i] > 0.0f) - cc->u[i] |= TGSI_EXEC_CC_GT << shift; - else if (dst->f[i] == 0.0f) - cc->u[i] |= TGSI_EXEC_CC_EQ << shift; - else - cc->u[i] |= TGSI_EXEC_CC_UN << shift; - } - } } #define FETCH(VAL,INDEX,CHAN)\ @@ -1687,10 +1545,8 @@ exec_kil(struct tgsi_exec_machine *mach, uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */ union tgsi_exec_channel r[1]; - /* This mask stores component bits that were already tested. Note that - * we test if the value is less than zero, so 1.0 and 0.0 need not to be - * tested. */ - uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE); + /* This mask stores component bits that were already tested. */ + uniquemask = 0; for (chan_index = 0; chan_index < 4; chan_index++) { @@ -1698,7 +1554,7 @@ exec_kil(struct tgsi_exec_machine *mach, uint i; /* unswizzle channel */ - swizzle = tgsi_util_get_full_src_register_extswizzle ( + swizzle = tgsi_util_get_full_src_register_swizzle ( &inst->FullSrcRegisters[0], chan_index); @@ -1726,32 +1582,8 @@ exec_kilp(struct tgsi_exec_machine *mach, { uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */ - if (inst->InstructionExtNv.CondFlowEnable) { - uint swizzle[4]; - uint chan_index; - - kilmask = 0x0; - - swizzle[0] = inst->InstructionExtNv.CondSwizzleX; - swizzle[1] = inst->InstructionExtNv.CondSwizzleY; - swizzle[2] = inst->InstructionExtNv.CondSwizzleZ; - swizzle[3] = inst->InstructionExtNv.CondSwizzleW; - - for (chan_index = 0; chan_index < 4; chan_index++) - { - uint i; - - for (i = 0; i < 4; i++) { - /* TODO: evaluate the condition code */ - if (0) - kilmask |= 1 << i; - } - } - } - else { - /* "unconditional" kil */ - kilmask = mach->ExecMask; - } + /* "unconditional" kil */ + kilmask = mach->ExecMask; mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask; } @@ -1979,8 +1811,8 @@ exec_declaration( break; default: - eval = NULL; assert( 0 ); + return; } if( mask == TGSI_WRITEMASK_XYZW ) { @@ -2029,10 +1861,23 @@ exec_instruction( break; case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { - FETCH( &r[0], 0, chan_index ); - STORE( &r[0], 0, chan_index ); + if (inst->Flags & SOA_DEPENDENCY_FLAG) { + /* Do all fetches into temp regs, then do all stores to avoid + * intermediate/accidental clobbering. This could be done all the + * time for MOV but for other instructions we'll need more temps... + */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[chan_index], 0, chan_index ); + } + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[chan_index], 0, chan_index ); + } + } + else { + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + STORE( &r[0], 0, chan_index ); + } } break; @@ -2313,16 +2158,6 @@ exec_instruction( } break; - case TGSI_OPCODE_CND0: - FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) { - FETCH(&r[0], 0, chan_index); - FETCH(&r[1], 1, chan_index); - FETCH(&r[2], 2, chan_index); - micro_le(&r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[2], &r[0], &r[1]); - STORE(&r[0], 0, chan_index); - } - break; - case TGSI_OPCODE_DP2A: FETCH( &r[0], 0, CHAN_X ); FETCH( &r[1], 1, CHAN_X ); @@ -2750,19 +2585,32 @@ exec_instruction( if (mach->ExecMask) { /* do the call */ - /* push the Cond, Loop, Cont stacks */ + /* First, record the depths of the execution stacks. + * This is important for deeply nested/looped return statements. + * We have to unwind the stacks by the correct amount. For a + * real code generator, we could determine the number of entries + * to pop off each stack with simple static analysis and avoid + * implementing this data structure at run time. + */ + mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop; + mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop; + mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop; + /* note that PC was already incremented above */ + mach->CallStack[mach->CallStackTop].ReturnAddr = *pc; + + mach->CallStackTop++; + + /* Second, push the Cond, Loop, Cont, Func stacks */ assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING); mach->CondStack[mach->CondStackTop++] = mach->CondMask; assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->ContStack[mach->ContStackTop++] = mach->ContMask; - assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING); mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask; - /* note that PC was already incremented above */ - mach->CallStack[mach->CallStackTop++] = *pc; + /* Finally, jump to the subroutine */ *pc = inst->InstructionExtLabel.Label; } break; @@ -2779,18 +2627,24 @@ exec_instruction( *pc = -1; return; } - *pc = mach->CallStack[--mach->CallStackTop]; - /* pop the Cond, Loop, Cont stacks */ - assert(mach->CondStackTop > 0); - mach->CondMask = mach->CondStack[--mach->CondStackTop]; - assert(mach->LoopStackTop > 0); - mach->LoopMask = mach->LoopStack[--mach->LoopStackTop]; - assert(mach->ContStackTop > 0); - mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->CallStackTop > 0); + mach->CallStackTop--; + + mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop; + mach->CondMask = mach->CondStack[mach->CondStackTop]; + + mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop; + mach->LoopMask = mach->LoopStack[mach->LoopStackTop]; + + mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop; + mach->ContMask = mach->ContStack[mach->ContStackTop]; + assert(mach->FuncStackTop > 0); mach->FuncMask = mach->FuncStack[--mach->FuncStackTop]; + *pc = mach->CallStack[mach->CallStackTop].ReturnAddr; + UPDATE_EXEC_MASK(mach); } break; @@ -3088,6 +2942,12 @@ exec_instruction( break; case TGSI_OPCODE_BGNFOR: + assert(mach->LoopCounterStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + for (chan_index = 0; chan_index < 3; chan_index++) { + FETCH( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[chan_index], 0, chan_index ); + } + STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X ); + ++mach->LoopCounterStackTop; /* fall-through (for now) */ case TGSI_OPCODE_BGNLOOP: /* push LoopMask and ContMasks */ @@ -3095,10 +2955,58 @@ exec_instruction( mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->ContStack[mach->ContStackTop++] = mach->ContMask; + assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1; break; case TGSI_OPCODE_ENDFOR: - /* fall-through (for now at least) */ + assert(mach->LoopCounterStackTop > 0); + micro_sub( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X], + &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] ); + /* update LoopMask */ + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[0] <= 0) { + mach->LoopMask &= ~0x1; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[1] <= 0 ) { + mach->LoopMask &= ~0x2; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[2] <= 0 ) { + mach->LoopMask &= ~0x4; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[3] <= 0 ) { + mach->LoopMask &= ~0x8; + } + micro_add( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Z]); + assert(mach->LoopLabelStackTop > 0); + inst = mach->Instructions + mach->LoopLabelStack[mach->LoopLabelStackTop - 1]; + STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X ); + /* Restore ContMask, but don't pop */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; + UPDATE_EXEC_MASK(mach); + if (mach->ExecMask) { + /* repeat loop: jump to instruction just past BGNLOOP */ + assert(mach->LoopLabelStackTop > 0); + *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1; + } + else { + /* exit loop: pop LoopMask */ + assert(mach->LoopStackTop > 0); + mach->LoopMask = mach->LoopStack[--mach->LoopStackTop]; + /* pop ContMask */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->LoopLabelStackTop > 0); + --mach->LoopLabelStackTop; + assert(mach->LoopCounterStackTop > 0); + --mach->LoopCounterStackTop; + } + UPDATE_EXEC_MASK(mach); + break; + case TGSI_OPCODE_ENDLOOP: /* Restore ContMask, but don't pop */ assert(mach->ContStackTop > 0); @@ -3106,7 +3014,8 @@ exec_instruction( UPDATE_EXEC_MASK(mach); if (mach->ExecMask) { /* repeat loop: jump to instruction just past BGNLOOP */ - *pc = inst->InstructionExtLabel.Label + 1; + assert(mach->LoopLabelStackTop > 0); + *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1; } else { /* exit loop: pop LoopMask */ @@ -3115,6 +3024,8 @@ exec_instruction( /* pop ContMask */ assert(mach->ContStackTop > 0); mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->LoopLabelStackTop > 0); + --mach->LoopLabelStackTop; } UPDATE_EXEC_MASK(mach); break; @@ -3141,22 +3052,6 @@ exec_instruction( /* no-op */ break; - case TGSI_OPCODE_NOISE1: - assert( 0 ); - break; - - case TGSI_OPCODE_NOISE2: - assert( 0 ); - break; - - case TGSI_OPCODE_NOISE3: - assert( 0 ); - break; - - case TGSI_OPCODE_NOISE4: - assert( 0 ); - break; - case TGSI_OPCODE_NOP: break; @@ -3182,7 +3077,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach ) mach->FuncMask = 0xf; mach->ExecMask = 0xf; - mach->CondStackTop = 0; /* temporarily subvert this assertion */ assert(mach->CondStackTop == 0); assert(mach->LoopStackTop == 0); assert(mach->ContStackTop == 0);