~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to erts/emulator/beam/beam_emu.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-02-15 16:42:52 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20090215164252-dxpjjuq108nz4noa
Tags: 1:12.b.5-dfsg-2
Upload to unstable after lenny is released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
222
222
 
223
223
#define ClauseFail() goto lb_jump_f
224
224
 
225
 
#define SAVE_CP(X)              *(X) = make_cp(c_p->cp)
 
225
#define SAVE_CP(X)                              \
 
226
   do {                                         \
 
227
      *(X) = make_cp(c_p->cp);                  \
 
228
      c_p->cp = 0;                              \
 
229
   } while(0)
 
230
 
226
231
#define RESTORE_CP(X)           SET_CP(c_p, cp_val(*(X)))
227
232
 
228
233
#define ISCATCHEND(instr) ((Eterm *) *(instr) == OpCode(catch_end_y))
233
238
 
234
239
Eterm beam_apply[2];
235
240
Eterm beam_exit[1];
 
241
Eterm beam_continue_exit[1];
236
242
 
237
243
Eterm* em_call_error_handler;
238
244
Eterm* em_apply_bif;
606
612
    (Dest) = (Src);                 \
607
613
    I = c_p->cp;                    \
608
614
    ASSERT(VALID_INSTR(*c_p->cp));  \
 
615
    c_p->cp = 0;                    \
609
616
    CHECK_TERM(r(0));               \
610
617
    Goto(*I)
611
618
 
1326
1333
     NextPF(1, next);
1327
1334
 }
1328
1335
 
1329
 
 OpCase(return):
 
1336
 OpCase(return): {
1330
1337
    SET_I(c_p->cp);
 
1338
    /*
 
1339
     * We must clear the CP to make sure that a stale value do not
 
1340
     * create a false module dependcy preventing code upgrading.
 
1341
     * It also means that we can use the CP in stack backtraces.
 
1342
     */
 
1343
    c_p->cp = 0;
1331
1344
    CHECK_TERM(r(0));
1332
1345
    Goto(*I);
 
1346
 }
1333
1347
 
1334
1348
 OpCase(test_heap_1_put_list_Iy): {
1335
1349
     Eterm* next;
1376
1390
         r(0) = result;
1377
1391
         CHECK_TERM(r(0));
1378
1392
         NextPF(0, next);
1379
 
     } else if (c_p->freason == RESCHEDULE) {
1380
 
         Eterm* argp;
1381
 
 
1382
 
         c_p->arity = 2;
1383
 
 
1384
 
         /*
1385
 
          * Moving c_p->arg to a register is shorter than using c_p->arg_reg
1386
 
          * directly, since c_p->arg_reg is a pointer (not an array)
1387
 
          * and the compiler generates code to fetch the pointer every time.
1388
 
          */
1389
 
         argp = c_p->arg_reg;
1390
 
         argp[0] = r(0);
1391
 
         argp[1] = x(1);
1392
 
         SWAPOUT;
1393
 
         c_p->i = I;
1394
 
         c_p->current = NULL;
1395
 
         goto do_schedule;
1396
1393
     } else if (c_p->freason == TRAP) {
1397
1394
         SET_CP(c_p, I+1);
1398
1395
         SET_I(((Export *)(c_p->def_arg_reg[3]))->address);
2039
2036
            r(0) = result;
2040
2037
            CHECK_TERM(r(0));
2041
2038
            NextPF(1, next);
2042
 
        } else if (c_p->freason == RESCHEDULE) {
2043
 
            c_p->arity = 1;
2044
 
            goto suspend_bif;
2045
2039
        } else if (c_p->freason == TRAP) {
2046
2040
            goto call_bif_trap3;
2047
2041
        }
2079
2073
            r(0) = result;
2080
2074
            CHECK_TERM(r(0));
2081
2075
            NextPF(1, next);
2082
 
        } else if (c_p->freason == RESCHEDULE) {
2083
 
            c_p->arity = 2;
2084
 
            goto suspend_bif;
2085
2076
        } else if (c_p->freason == TRAP) {
2086
2077
            goto call_bif_trap3;
2087
2078
        }
2117
2108
            r(0) = result;
2118
2109
            CHECK_TERM(r(0));
2119
2110
            NextPF(1, next);
2120
 
        } else if (c_p->freason == RESCHEDULE) {
2121
 
            c_p->arity = 3;
2122
 
            goto suspend_bif;
2123
2111
        } else if (c_p->freason == TRAP) {
2124
2112
        call_bif_trap3:
2125
2113
            SET_CP(c_p, I+2);
2595
2583
          */
2596
2584
         Uint size = c_p->arity * sizeof(c_p->arg_reg[0]);
2597
2585
         if (c_p->arg_reg != c_p->def_arg_reg) {
2598
 
             ERTS_PROC_LESS_MEM(c_p->max_arg_reg * sizeof(c_p->arg_reg[0]));
2599
 
             ERTS_PROC_MORE_MEM(size);
2600
2586
             c_p->arg_reg = (Eterm *) erts_realloc(ERTS_ALC_T_ARG_REG,
2601
2587
                                                   (void *) c_p->arg_reg,
2602
2588
                                                   size);
2603
2589
         } else {
2604
 
             ERTS_PROC_MORE_MEM(size);
2605
2590
             c_p->arg_reg = (Eterm *) erts_alloc(ERTS_ALC_T_ARG_REG, size);
2606
2591
         }
2607
2592
         c_p->max_arg_reg = c_p->arity;
2629
2614
     SWAPOUT;
2630
2615
     c_p->i = I;
2631
2616
     erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_STATUS);
2632
 
     add_to_schedule_q(c_p);
 
2617
     if (c_p->status != P_SUSPENDED)
 
2618
         add_to_schedule_q(c_p);
2633
2619
     erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_STATUS);
2634
2620
     goto do_schedule1;
2635
2621
 }
2777
2763
     goto do_schedule;
2778
2764
 }
2779
2765
 
2780
 
    /*
2781
 
     * Suspend BIF and prepare BIF to be rescheduled.
2782
 
     */
2783
 
 suspend_bif: {
2784
 
     Eterm* argp = c_p->arg_reg;
2785
 
     argp[0] = r(0);
2786
 
     argp[1] = x(1);
2787
 
     argp[2] = x(2);
2788
 
     SWAPOUT;
2789
 
     c_p->i = I;
2790
 
     c_p->current = NULL;
 
2766
 OpCase(continue_exit): {
 
2767
     ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
 
2768
     erts_continue_exit_process(c_p);
 
2769
     ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p);
2791
2770
     goto do_schedule;
2792
2771
 }
2793
2772
 
2969
2948
            CHECK_TERM(r(0));
2970
2949
            SET_I(c_p->cp);
2971
2950
            Goto(*I);
2972
 
        } else if (c_p->freason == RESCHEDULE) {
2973
 
            Eterm* argp = c_p->arg_reg;
2974
 
 
2975
 
            c_p->arity = I[-1];
2976
 
            argp[0] = r(0);
2977
 
            argp[1] = x(1);
2978
 
            argp[2] = x(2);
2979
 
            SWAPOUT;
2980
 
            c_p->i = I;
2981
 
            c_p->current = NULL;
2982
 
            goto do_schedule;
2983
2951
        } else if (c_p->freason == TRAP) {
2984
2952
            SET_I(((Export *)(c_p->def_arg_reg[3]))->address);
2985
2953
            r(0) = c_p->def_arg_reg[0];
3463
3431
 }
3464
3432
 
3465
3433
 /*
 
3434
  * Calculate the number of bytes needed to encode the source
 
3435
  * operarand to UTF-8. If the source operand is invalid (e.g. wrong
 
3436
  * type or range) we return a nonsense integer result (0 or 4). We
 
3437
  * can get away with that because we KNOW that bs_put_utf8 will do
 
3438
  * full error checking.
 
3439
  */
 
3440
 OpCase(i_bs_utf8_size_sd): {
 
3441
     Eterm arg;
 
3442
     Eterm result;
 
3443
 
 
3444
     GetArg1(0, arg);
 
3445
     if (arg < make_small(0x80UL)) {
 
3446
         result = make_small(1);
 
3447
     } else if (arg < make_small(0x800UL)) {
 
3448
         result = make_small(2);
 
3449
     } else if (arg < make_small(0x10000UL)) {
 
3450
         result = make_small(3);
 
3451
     } else {
 
3452
         result = make_small(4);
 
3453
     }
 
3454
     StoreBifResult(1, result);
 
3455
 }
 
3456
 
 
3457
 OpCase(i_bs_put_utf8_js): {
 
3458
     Eterm arg;
 
3459
 
 
3460
     GetArg1(1, arg);
 
3461
     if (!erts_bs_put_utf8(ERL_BITS_ARGS_1(arg))) {
 
3462
         goto badarg;
 
3463
     }
 
3464
     Next(2);
 
3465
 }
 
3466
 
 
3467
 /*
 
3468
  * Calculate the number of bytes needed to encode the source
 
3469
  * operarand to UTF-8. If the source operand is invalid (e.g. wrong
 
3470
  * type or range) we return a nonsense integer result (2 or 4). We
 
3471
  * can get away with that because we KNOW that bs_put_utf16 will do
 
3472
  * full error checking.
 
3473
  */
 
3474
 
 
3475
 OpCase(i_bs_utf16_size_sd): {
 
3476
     Eterm arg;
 
3477
     Eterm result = make_small(2);
 
3478
 
 
3479
     GetArg1(0, arg);
 
3480
     if (arg >= make_small(0x10000UL)) {
 
3481
         result = make_small(4);
 
3482
     }
 
3483
     StoreBifResult(1, result);
 
3484
 }
 
3485
 
 
3486
 OpCase(i_bs_put_utf16_jIs): {
 
3487
     Eterm arg;
 
3488
 
 
3489
     GetArg1(2, arg);
 
3490
     if (!erts_bs_put_utf16(ERL_BITS_ARGS_2(arg, Arg(1)))) {
 
3491
         goto badarg;
 
3492
     }
 
3493
     Next(3);
 
3494
 }
 
3495
 
 
3496
 /*
 
3497
  * Only used for validating a value about to be stored in a binary.
 
3498
  */
 
3499
 OpCase(i_bs_validate_unicode_js): {
 
3500
     Eterm val;
 
3501
 
 
3502
     GetArg1(1, val);
 
3503
 
 
3504
     /*
 
3505
      * There is no need to untag the integer, but it IS necessary
 
3506
      * to make sure it is small (if the term is a bignum, it could
 
3507
      * slip through the test, and there is no further test that
 
3508
      * would catch it, since bit syntax construction silently masks
 
3509
      * too big numbers).
 
3510
      */
 
3511
     if (is_not_small(val) || val > make_small(0x10FFFFUL) ||
 
3512
         (make_small(0xD800UL) <= val && val <= make_small(0xDFFFUL)) ||
 
3513
         val == make_small(0xFFFEUL) || val == make_small(0xFFFFUL)) {
 
3514
         goto badarg;
 
3515
     }
 
3516
     Next(2);
 
3517
 }
 
3518
 
 
3519
 /*
 
3520
  * Only used for validating a value matched out. 
 
3521
  *
 
3522
  * tmp_arg1 = Integer to validate
 
3523
  * tmp_arg2 = Match context
 
3524
  */
 
3525
 OpCase(i_bs_validate_unicode_retract_j): {
 
3526
     /*
 
3527
      * There is no need to untag the integer, but it IS necessary
 
3528
      * to make sure it is small (a bignum pointer could fall in
 
3529
      * the valid range).
 
3530
      */
 
3531
     if (is_not_small(tmp_arg1) || tmp_arg1 > make_small(0x10FFFFUL) ||
 
3532
         (make_small(0xD800UL) <= tmp_arg1 && tmp_arg1 <= make_small(0xDFFFUL)) ||
 
3533
         tmp_arg1 == make_small(0xFFFEUL) || tmp_arg1 == make_small(0xFFFFUL)) {
 
3534
         ErlBinMatchBuffer *mb = ms_matchbuffer(tmp_arg2);
 
3535
 
 
3536
         mb->offset -= 32;
 
3537
         goto badarg;
 
3538
     }
 
3539
     Next(1);
 
3540
 }
 
3541
 
 
3542
 /*
3466
3543
  * Matching of binaries.
3467
3544
  */
3468
3545
 
3684
3761
     _mb = ms_matchbuffer(tmp_arg1);
3685
3762
     if (_mb->size - _mb->offset < 32) { ClauseFail(); }
3686
3763
     if (BIT_OFFSET(_mb->offset) != 0) {
3687
 
         _integer = erts_bs_get_unaligned_uint32(c_p, _mb);
 
3764
         _integer = erts_bs_get_unaligned_uint32(_mb);
3688
3765
     } else {
3689
3766
         _integer = get_int32(_mb->base + _mb->offset/8);
3690
3767
     }
3796
3873
     StoreBifResult(3, result);
3797
3874
 }
3798
3875
 
 
3876
 /* Operands: MatchContext Fail Dst */
 
3877
 OpCase(i_bs_get_utf8_rfd): {
 
3878
     tmp_arg1 = r(0);
 
3879
     goto do_bs_get_utf8;
 
3880
 }
 
3881
 
 
3882
 OpCase(i_bs_get_utf8_xfd): {
 
3883
     tmp_arg1 = xb(Arg(0));
 
3884
     I++;
 
3885
 }
 
3886
 
 
3887
 /*
 
3888
  * tmp_arg1 = match_context
 
3889
  * Operands: Fail Dst
 
3890
  */
 
3891
 
 
3892
    do_bs_get_utf8: {
 
3893
     ErlBinMatchBuffer* _mb;
 
3894
     Eterm result;
 
3895
     Uint remaining_bits;
 
3896
     byte* pos;
 
3897
     byte tmp_buf[4];
 
3898
     Eterm a, b, c;
 
3899
 
 
3900
     /*
 
3901
      * Number of trailing bytes for each value of the first byte.
 
3902
      */
 
3903
     static const byte erts_trailing_bytes_for_utf8[256] = {
 
3904
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 
3905
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 
3906
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 
3907
         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 
3908
         9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
 
3909
         9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
 
3910
         9,9,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 
3911
         2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,9,9,9,9,9,9,9,9
 
3912
     };
 
3913
 
 
3914
     _mb = ms_matchbuffer(tmp_arg1);
 
3915
     if ((remaining_bits = _mb->size - _mb->offset) < 8) {
 
3916
         ClauseFail();
 
3917
     }
 
3918
     if (BIT_OFFSET(_mb->offset) == 0) {
 
3919
         pos = _mb->base + BYTE_OFFSET(_mb->offset);
 
3920
     } else {
 
3921
         erts_align_utf8_bytes(_mb, tmp_buf);
 
3922
         pos = tmp_buf;
 
3923
     }
 
3924
     result = pos[0];
 
3925
     switch (erts_trailing_bytes_for_utf8[result]) {
 
3926
     case 0:
 
3927
         /* One byte only */
 
3928
         _mb->offset += 8;
 
3929
         break;
 
3930
     case 1:
 
3931
         /* Two bytes */
 
3932
         if (remaining_bits < 16) {
 
3933
             ClauseFail();
 
3934
         }
 
3935
         a = pos[1];
 
3936
         if ((a & 0xC0) != 0x80) {
 
3937
             ClauseFail();
 
3938
         }
 
3939
         result = (result << 6) + a - (Eterm) 0x00003080UL;
 
3940
         _mb->offset += 16;
 
3941
         break;
 
3942
     case 2:
 
3943
         /* Three bytes */
 
3944
 
 
3945
         if (remaining_bits < 24) {
 
3946
             ClauseFail();
 
3947
         }
 
3948
         a = pos[1];
 
3949
         b = pos[2];
 
3950
         if ((a & 0xC0) != 0x80 || (b & 0xC0) != 0x80 ||
 
3951
             (result == 0xE0 && a < 0xA0)) {
 
3952
             ClauseFail();
 
3953
         }
 
3954
         result = (((result << 6) + a) << 6) + b - (Eterm) 0x000E2080UL;
 
3955
         if ((0xD800 <= result && result <= 0xDFFF) ||
 
3956
             result == 0xFFFE || result == 0xFFFF) {
 
3957
             ClauseFail();
 
3958
         }
 
3959
         _mb->offset += 24;
 
3960
         break;
 
3961
     case 3:
 
3962
         /* Four bytes */
 
3963
 
 
3964
         if (remaining_bits < 32) {
 
3965
             ClauseFail();
 
3966
         }
 
3967
         a = pos[1];
 
3968
         b = pos[2];
 
3969
         c = pos[3];
 
3970
         if ((a & 0xC0) != 0x80 || (b & 0xC0) != 0x80 ||
 
3971
             (c & 0xC0) != 0x80 ||
 
3972
             (result == 0xF0 && a < 0x90)) {
 
3973
             ClauseFail();
 
3974
         }
 
3975
         result = (((((result << 6) + a) << 6) + b) << 6) +
 
3976
             c - (Eterm) 0x03C82080UL;
 
3977
         if (result > 0x10FFFF) {
 
3978
             ClauseFail();
 
3979
         }
 
3980
         _mb->offset += 32;
 
3981
         break;
 
3982
     default:
 
3983
         ClauseFail();
 
3984
     }
 
3985
     result = make_small(result);
 
3986
     StoreBifResult(1, result);
 
3987
 }
 
3988
 
 
3989
 /* Operands: MatchContext Fail Flags Dst */
 
3990
 OpCase(i_bs_get_utf16_rfId): {
 
3991
     tmp_arg1 = r(0);
 
3992
     goto do_bs_get_utf16;
 
3993
 }
 
3994
 
 
3995
 OpCase(i_bs_get_utf16_xfId): {
 
3996
     tmp_arg1 = xb(Arg(0));
 
3997
     I++;
 
3998
 }
 
3999
 
 
4000
 /*
 
4001
  * tmp_arg1 = match_context
 
4002
  * Operands: Fail Flags Dst
 
4003
  */
 
4004
    do_bs_get_utf16: {
 
4005
     Eterm result = erts_bs_get_utf16(ms_matchbuffer(tmp_arg1), Arg(1));
 
4006
     if (is_non_value(result)) {
 
4007
         ClauseFail();
 
4008
     }
 
4009
     StoreBifResult(2, result);
 
4010
 }
 
4011
 
3799
4012
 {
3800
4013
     ErlBinMatchBuffer* mb;
3801
4014
     ErlSubBin* sb;
4167
4380
     Goto(*I);
4168
4381
 }
4169
4382
 
 
4383
#ifdef HIPE     /* XXX: temporary fix for R12B-5, will go away before R13 */
4170
4384
 /*
4171
4385
  * Instructions for module_info/0,1.
4172
4386
  */
4173
4387
 
4174
 
 OpCase(i_module_info_0): {
 
4388
 OpCase(hipe_module_info_0): {
4175
4389
     SWAPOUT;
4176
4390
     r(0) = erts_module_info_0(c_p, I[-3]);
4177
4391
     HTOP = HEAP_TOP(c_p);
4179
4393
     Goto(*I);
4180
4394
 }
4181
4395
 
4182
 
 OpCase(i_module_info_1): {
 
4396
 OpCase(hipe_module_info_1): {
4183
4397
     Eterm res;
4184
4398
 
4185
4399
     SWAPOUT;
4194
4408
     c_p->current = I-3;
4195
4409
     goto lb_error_action_code;
4196
4410
 }
 
4411
#endif
4197
4412
 
4198
4413
 /*
4199
4414
  * Instructions for allocating on the message area.
4457
4672
         cmd = HIPE_MODE_SWITCH_CMD_RESUME;
4458
4673
         goto L_hipe_mode_switch;
4459
4674
     }
4460
 
     OpCase(hipe_trap_reschedule): {
4461
 
         cmd = HIPE_MODE_SWITCH_CMD_RESCHEDULE;
4462
 
         goto L_hipe_mode_switch;
4463
 
     }
4464
4675
 L_hipe_mode_switch:
4465
4676
     /* XXX: this abuse of def_arg_reg[] is horrid! */
4466
4677
     SWAPOUT;
4623
4834
     beam_apply[0] = (Eterm) OpCode(i_apply);
4624
4835
     beam_apply[1] = (Eterm) OpCode(normal_exit);
4625
4836
     beam_exit[0] = (Eterm) OpCode(error_action_code);
 
4837
     beam_continue_exit[0] = (Eterm) OpCode(continue_exit);
4626
4838
     beam_return_to_trace[0] = (Eterm) OpCode(i_return_to_trace);
4627
4839
     beam_return_trace[0] = (Eterm) OpCode(return_trace);
4628
4840
     beam_exception_trace[0] = (Eterm) OpCode(return_trace); /* UGLY */
4747
4959
    c_p->i = pc;    /* In case we call erl_exit(). */
4748
4960
 
4749
4961
    ASSERT(c_p->freason != TRAP); /* Should have been handled earlier. */
4750
 
    ASSERT(c_p->freason != RESCHEDULE); /* Should have been handled earlier. */
4751
4962
 
4752
4963
    /*
4753
4964
     * Check if we have an arglist for the top level call. If so, this
4805
5016
        reg[1] = exception_tag[GET_EXC_CLASS(c_p->freason)];
4806
5017
        reg[2] = Value;
4807
5018
        reg[3] = c_p->ftrace;
4808
 
        if ( (new_pc = next_catch(c_p, reg))) return new_pc;
 
5019
        if ((new_pc = next_catch(c_p, reg))) {
 
5020
            c_p->cp = 0;        /* To avoid keeping stale references. */
 
5021
            return new_pc;
 
5022
        }
4809
5023
        if (c_p->catches > 0) erl_exit(1, "Catch not found");
4810
5024
    }
4811
5025
    ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p);
5041
5255
            s->trace[s->depth++] = pc;
5042
5256
            depth--;
5043
5257
        }
 
5258
        /* Save second stack entry if CP is valid and different from pc */
 
5259
        if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) {
 
5260
            s->trace[s->depth++] = c_p->cp;
 
5261
            depth--;
 
5262
        }
5044
5263
        s->pc = NULL;
5045
5264
        args = make_arglist(c_p, reg, a); /* Overwrite CAR(c_p->ftrace) */
5046
5265
    } else {
5063
5282
            }
5064
5283
            s->pc = NULL; /* Ignore pc */
5065
5284
        } else {
 
5285
            if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) {
 
5286
                s->trace[s->depth++] = c_p->cp;
 
5287
                depth--;
 
5288
            }
5066
5289
            s->pc = pc;
5067
5290
        }
5068
5291
    }
5577
5800
 
5578
5801
    if (c_p->arg_reg != c_p->def_arg_reg) {
5579
5802
        /* Save some memory */
5580
 
        ERTS_PROC_LESS_MEM(c_p->max_arg_reg * sizeof(c_p->arg_reg[0]));
5581
5803
        erts_free(ERTS_ALC_T_ARG_REG, c_p->arg_reg);
5582
5804
        c_p->arg_reg = c_p->def_arg_reg;
5583
5805
        c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]);