Changeset 14965


Ignore:
Timestamp:
Aug 31, 2011, 3:11:12 AM (13 years ago)
Author:
Gary Byers
Message:

Treat s28-s31 (save0-save3) as non-volatile node-bearing regs; it
may be cheaper to access values in such registers than it would be
to access memory.

When entering lisp context (thread entry/callback), save all non-volatile
FP regs (d8-d15) and load benign values into s28-s31. When creating a
lisp catch frame, save d8-d13 in a stack-consed vector and s28-s31 in
new slots in the catch frame.

C code only needs to know about catch frame layout to support thread
reset from C, and that hasn't worked in a long time. If C code ever
needs this info, should define the ARM (not PPC) version.

On Linux, vfp state is maintained as a tagged record in the
uc_regspace field of a ucontext stucture; there can be other tagged
records (Marvell CPUs may contain iwmmxt info, for instance.) Some
comments in header files (somewhere) suggest that only certain
exception contexts contain vfp state; other comments suggest that
those comments have been bogus for a long time. This whole scheme
obviously depends on the GC being able to find non-null VFP info in
any exception context it processes. mark_xp() checks for that and enters
the kernel debugger if it's missing; forward_xp() assumes that mark_xp()
has checked.

Make the l and r kernel debugger commands print the values of save0-save3
and make the f command ignore them.

Since the lisp side of things is (currently) blissfully unaware of all
this, save0-save3 should (at the moment) always contain "benign values"
(0).

Location:
trunk/source/lisp-kernel
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/lisp-kernel/arm-constants.h

    r14270 r14965  
    4040#define nargs imm2
    4141#define allocbase temp0         /* while consing */
     42
     43/* Non-volatile pseudo node regs kept in s28-s31 */
     44#define save0 28
     45#define save1 29
     46#define save2 30
     47#define save3 31
    4248
    4349#define nbits_in_word 32
     
    220226
    221227
    222 /*
    223   The GC also needs to know what a catch_frame looks like.
    224 */
    225 
    226 typedef struct catch_frame {
    227   LispObj header;
    228   LispObj catch_tag;
    229   LispObj link;
    230   LispObj mvflag;
    231   LispObj csp;
    232   LispObj db_link;
    233   LispObj regs[8];
    234   LispObj xframe;
    235   LispObj tsp_segment;
    236 } catch_frame;
    237 
    238 #define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
    239 #define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
    240228
    241229typedef struct lisp_frame {
  • trunk/source/lisp-kernel/arm-constants.s

    r14119 r14965  
    6565define(`pc',`r15')
    6666
     67/* We can keep node values in some single-float registers.  By definition,
     68   those registers aren't general-purpose, but copying between them and
     69   GPRs may be faster than using the stack would be. */
     70define(`save0',`s28')
     71define(`save1',`s29')
     72define(`save2',`s30')
     73define(`save3',`s31')
     74                                               
    6775nargregs = 3
    6876               
     
    321329         _node(last_lisp_frame) /* from TCR */
    322330         _node(code_vector)     /* of fn in lisp_frame, or 0 */
     331         _field(nvrs,4*node_size)
    323332        _endstructf
    324333
     
    658667r15 = 15
    659668pc = 15
     669               
    660670       
    661        
    662 /* Lisp code keeps 0.0 in fp_zero */
    663 define(`fp_zero',`f31')   /* a non-volatile reg as far as FFI is concerned. */
    664 define(`fp_s32conv',`f30')   /* for s32->fp conversion */
    665671       
    666672/* registers, as used in destrucuring-bind/macro-bind */
  • trunk/source/lisp-kernel/arm-exceptions.c

    r14876 r14965  
    610610reset_lisp_process(ExceptionInformation *xp)
    611611{
     612#if 0
    612613  TCR *tcr = get_tcr(true);
    613614  catch_frame *last_catch = (catch_frame *) ptr_from_lispobj(untag(tcr->catch_top));
     
    618619
    619620  start_lisp(tcr, 1);
     621#endif
    620622}
    621623
  • trunk/source/lisp-kernel/arm-gc.c

    r14939 r14965  
    10551055mark_xp(ExceptionInformation *xp)
    10561056{
     1057#ifdef LINUX
     1058  void *find_vfp_info(ExceptionInformation *);
     1059#endif
    10571060  natural *regs = (natural *) xpGPRvector(xp);
    10581061  int r;
     
    10701073    mark_root((regs[r]));
    10711074  }
    1072 
     1075#ifdef LINUX
     1076  {
     1077    LispObj *vfp_info = (LispObj *)find_vfp_info(xp);
     1078    int nvr;
     1079
     1080    if (vfp_info == NULL) {
     1081      Bug(NULL, "No VFP info in exception context!");
     1082    }
     1083   
     1084    for (nvr = save0;nvr <= save3;nvr++) {
     1085      mark_root(vfp_info[nvr]);
     1086    }
     1087  }
     1088#endif
    10731089
    10741090
    10751091  mark_pc_root(ptr_to_lispobj(xpPC(xp)));
    10761092  mark_pc_root(ptr_to_lispobj(xpLR(xp)));
     1093 
    10771094}
    10781095
     
    13511368  }
    13521369
     1370#ifdef LINUX
     1371  {
     1372    void *find_vfp_info(ExceptionInformation *);
     1373    LispObj* nvrs = (LispObj *)find_vfp_info(xp);
     1374
     1375    for (r=save0;r<=save3;r++) {
     1376      update_noderef(&nvrs[r]);
     1377    }
     1378  }
     1379#endif
    13531380
    13541381  update_locref((LispObj*) (&(xpPC(xp))));
  • trunk/source/lisp-kernel/arm-macros.s

    r14823 r14965  
    333333*/       
    334334   
    335 define(`push_fprs',`
     335define(`push_foreign_fprs',`
    336336        __(movc16(imm0,make_header(8,subtag_double_float_vector)))
    337337        __(mov imm1,#0)
     
    340340')
    341341
     342/* Save the lisp non-volatile FPRs. */
     343define(`push_lisp_fprs',`
     344        __(movc16(imm0,make_header(6,subtag_double_float_vector)))
     345        __(mov imm1,#0)
     346        __(fmdrr d7,imm0,imm1)
     347        __(fstmfdd sp!,{d7-d13})
     348')
     349       
    342350/* Pop the non-volatile FPRs (d8-d15) from the stack-consed vector
    343351   on top of the stack.  This loads the vector header
    344352   into d7 as a side-effect. */
    345 define(`pop_fprs',`
     353define(`pop_foreign_fprs',`
    346354        __(fldmfdd sp!,{d7-d15})
    347355')
    348356
    349 /* Reload the non-volatile FPRs (d8-d15) from the stack-consed vector
     357/* Pop the lisp non-volatile FPRs */       
     358define(`pop_lisp_fprs',`
     359        __(fldmfdd sp!,{d7-d13})
     360')
     361
     362/* Reload the non-volatile lisp FPRs (d8-d13) from the stack-consed vector
    350363   on top of the stack, leaving the vector in place.  d7 winds up with
    351364   a denormalized float in it, if anything cares. */
    352 define(`restore_fprs',`
    353         __(fldmfdd $1,{d7-d15})
     365define(`restore_lisp_fprs',`
     366        __(fldmfdd $1,{d7-d13})
    354367')               
    355368
    356369/* discard the stack-consed vector which contains a set of 8 non-volatile
    357370   FPRs. */
    358 define(`discard_fprs',`
    359         __(add sp,sp,#9*8)
     371define(`discard_lisp_fprs',`
     372        __(add sp,sp,#7*8)
    360373')                       
    361374       
    362375define(`mkcatch',`
    363376        new_macro_labels()
    364         __(push_fprs())
     377        __(push_lisp_fprs())
    365378        __(build_lisp_frame(imm0))
     379        __(movc16(imm0,make_header(catch_frame.element_count,subtag_u32_vector)))
     380        __(mov imm1,#catch_frame.element_count<<word_shift)
     381        __(dnode_align(imm1,imm1,node_size))
     382        __(stack_allocate_zeroed_ivector(imm0,imm1))
    366383        __(movc16(imm0,make_header(catch_frame.element_count,subtag_catch_frame)))
    367384        __(movs temp2,fn)
     
    373390        __(ldr arg_x,[rcontext,#tcr.db_link])
    374391        __(ldr temp0,[rcontext,#tcr.xframe])
    375         __(stmdb sp!,{imm0,imm1,imm2,arg_z,arg_x,temp0,temp1,temp2})
     392        __(stmia sp,{imm0,imm1,imm2,arg_z,arg_x,temp0,temp1,temp2})
    376393        __(add imm0,sp,#fulltag_misc)
    377394        __(str imm0,[rcontext,#tcr.catch_top])
     395        __(add imm0,imm0,#catch_frame.nvrs)
     396        __(fstmias imm0,{save0-save3})
    378397        __(add lr,lr,#4)
    379398')     
  • trunk/source/lisp-kernel/arm-spentry.s

    r14845 r14965  
    23492349_spentry(progvrestore)
    23502350        __(skip_stack_vector(imm0,imm1,sp))
    2351         __(ldr imm0,[imm0,#lisp_frame.size+(9*8)+node_size]) /* 9*8 = size of saved FPR vector, with header */
     2351        __(ldr imm0,[imm0,#lisp_frame.size+(7*8)+node_size]) /* 7*8 = size of saved FPR vector, with header */
    23522352        __(cmp imm0,#0)
    23532353        __(unbox_fixnum(imm0,imm0))
     
    28592859        __(ldr arg_y,[rcontext,#tcr.last_lisp_frame])
    28602860        __(stmdb vsp!,{arg_y,arg_x,temp0,temp1,temp2})
     2861        __(fstmdbs vsp!,{save0-save3})
    28612862        __(str vsp,[rcontext,#tcr.save_vsp])
    28622863/* There's a u32 vector on top of the stack ; its first data word points
     
    28942895        __(mov arg_x,#0)
    28952896        __(mov fn,#0)
     2897        __(fmsr save0,arg_z)
     2898        __(fcpys save1,save0)
     2899        __(fcpys save2,save0)
     2900        __(fcpys save3,save0)
    28962901        __(mov allocptr,#VOID_ALLOCPTR)
    28972902        __(mov rcontext,temp0)
     
    29002905        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
    29012906        __(restore_lisp_frame(temp0))
     2907        __(fldmias vsp!,{save0-save3})
    29022908        __(ldmia vsp!,{arg_y,arg_x,temp0,temp1,temp2})
    29032909        __(str arg_y,[rcontext,#tcr.last_lisp_frame])
     
    31073113        __(orr imm0,imm0,#subtag_u32_vector)
    31083114        __(stmdb sp!,{imm0,imm2})
     3115        __(push_foreign_fprs())
    31093116        __(mov arg_x,#0)
    31103117        __(mov temp0,#0)
     
    31143121        __(mov fn,#0)
    31153122        __(ldr vsp,[rcontext,#tcr.save_vsp])
     3123        __(fmsr save0,arg_z)
     3124        __(fcpys save1,save0)
     3125        __(fcpys save2,save0)
     3126        __(fcpys save3,save0)       
    31163127        __(mov imm0,#TCR_STATE_LISP)
    31173128        __(str imm0,[rcontext,#tcr.valence])
     
    31233134        __(blx lr)
    31243135        __(str vsp,[rcontext,#tcr.save_vsp])
    3125         __(ldr imm1,[sp,#4])
     3136        __(ldr imm1,[sp,#(9*8)+4])
    31263137        __(str imm1,[rcontext,#tcr.last_lisp_frame])
    31273138        __(str allocptr,[rcontext,#tcr.save_allocptr])
    31283139        __(mov imm0,#TCR_STATE_FOREIGN)
    31293140        __(str imm0,[rcontext,#tcr.valence])
     3141        __(pop_foreign_fprs())
    31303142        __(ldr sp,[sp,#node_size*2])   /* drop the ivector that hides foreign stack contents and restore (possibly misaligned) sp */
    31313143        __(ldmia sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr})
     
    39873999        __(ldr imm0,[temp0,#catch_frame.link])
    39884000        __(str imm0,[rcontext,#tcr.catch_top])
     4001        __(add imm0,sp,#catch_frame.nvrs+fulltag_misc)
     4002        __(fldmias imm0,{save0-save3})
    39894003        __(ldr fn,[sp,#catch_frame.size+lisp_frame.savefn])
    39904004        __(ldr lr,[sp,#catch_frame.size+lisp_frame.savelr])
    39914005        __(add sp,sp,#catch_frame.size+lisp_frame.size)
    3992         __(pop_fprs())
     4006        __(pop_lisp_fprs())
    39934007        __(bx lr)
    39944008_endfn(C(_throw_found))       
     
    40194033        __(ldreq vsp,[sp,#catch_frame.size+lisp_frame.savevsp])
    40204034        __(add sp,sp,#catch_frame.size+lisp_frame.size)
    4021         __(pop_fprs())
     4035        __(pop_lisp_fprs())
    40224036        __(b local_label(_nthrow1v_nextframe))
    40234037local_label(_nthrow1v_do_unwind):
     
    40264040        /* Save our caller's LR and FN in the csp frame created by the unwind-  */
    40274041        /* protect.  (Clever, eh ?)  */
     4042        __(flds save0,[sp,#fulltag_misc+catch_frame.nvrs+(0*node_size)])
     4043        __(flds save1,[sp,#fulltag_misc+catch_frame.nvrs+(1*node_size)])
     4044        __(flds save2,[sp,#fulltag_misc+catch_frame.nvrs+(2*node_size)])
     4045        __(flds save3,[sp,#fulltag_misc+catch_frame.nvrs+(3*node_size)])
    40284046        __(add sp,sp,#catch_frame.size)
    40294047        /* We used to use a swp instruction to exchange the lr with
     
    40554073        __(mov fn,nfn)
    40564074        __(add temp0,temp0,#lisp_frame.size)
    4057         __(restore_fprs(temp0))
     4075        __(restore_lisp_fprs(temp0))
    40584076        __(str imm1,[rcontext,#tcr.unwinding])
    40594077        __(blx lr)
     
    40644082        __(add sp,sp,#4*node_size)
    40654083        __(restore_lisp_frame(imm0))
    4066         __(discard_fprs())
     4084        __(discard_lisp_fprs())
    40674085        __(b local_label(_nthrow1v_nextframe))
    40684086local_label(_nthrow1v_done):
     
    41114129local_label(nthrownv_skip):     
    41124130        __(add sp,sp,#catch_frame.size+lisp_frame.size)
    4113         __(pop_fprs())
     4131        __(pop_lisp_fprs())         
    41144132        __(b local_label(nthrownv_nextframe))               
    41154133local_label(nthrownv_do_unwind):
     
    41194137        __(str arg_x,[rcontext,#tcr.xframe])
    41204138        __(str arg_z,[rcontext,#tcr.last_lisp_frame])
     4139        __(flds save0,[sp,#fulltag_misc+catch_frame.nvrs+(0*node_size)])
     4140        __(flds save1,[sp,#fulltag_misc+catch_frame.nvrs+(1*node_size)])
     4141        __(flds save2,[sp,#fulltag_misc+catch_frame.nvrs+(2*node_size)])
     4142        __(flds save3,[sp,#fulltag_misc+catch_frame.nvrs+(3*node_size)])
    41214143        __(add sp,sp,#catch_frame.size)
    41224144        __(add imm1,nargs,#node_size)
     
    41524174        __(ldr vsp,[arg_z,#lisp_frame.savevsp])
    41534175        __(add arg_z,arg_z,#lisp_frame.size)
    4154         __(restore_fprs(arg_z))
     4176        __(restore_lisp_fprs(arg_z))
    41554177        __(str imm1,[rcontext,#tcr.unwinding])
    41564178        __(mov fn,nfn)
     
    41774199        __(ldr lr,[sp,#lisp_frame.savelr])
    41784200        __(discard_lisp_frame())
    4179         __(discard_fprs())
     4201        __(discard_lisp_fprs())
    41804202        __(b local_label(nthrownv_nextframe))
    41814203local_label(nthrownv_done):     
     
    43704392        __(orr imm0,imm0,#subtag_u32_vector)
    43714393        __(stmdb sp!,{imm0,imm2})
     4394        __(push_foreign_fprs())
     4395        __(fmsr save0,arg_z)
     4396        __(fcpys save1,save0)
     4397        __(fcpys save2,save0)
     4398        __(fcpys save3,save0)       
    43724399        __(mov imm0,#TCR_STATE_LISP)
    43734400        __(str imm0,[rcontext,#tcr.valence])
    43744401        __(ldr allocptr,[rcontext,#tcr.save_allocptr])
    43754402        __(bl toplevel_loop)
    4376         __(ldmia sp!,{imm0,imm1})
     4403        __(ldr imm1,[sp,#(9*8)+4])
    43774404        __(mov imm0,#TCR_STATE_FOREIGN)
    43784405        __(str imm1,[rcontext,#tcr.last_lisp_frame])
    43794406        __(str imm0,[rcontext,#tcr.valence])
     4407        __(pop_foreign_fprs())
     4408        __(add sp,sp,#2*node_size)
    43804409        __(mov imm0,#nil_value)
    43814410        __(ldr sp,[sp])
  • trunk/source/lisp-kernel/lisp-debug.c

    r14837 r14965  
    5454#else
    5555char *kernel_svn_revision = "unknown";
     56#endif
     57
     58#ifdef ARM
     59#ifdef LINUX
     60
     61/* This stuff is buried in kernel headers.  Why ? */
     62
     63/* The uc_regspace field of a ucontext can contain coprocessor
     64   info in structures whose first word is one of these magic
     65   values; the structure list is terminated by something that's
     66   not one of these magic values.
     67
     68   Good thinking! That'll make the mechanism easy to extend!
     69   (In practice, a word of 0 seems to terminate the structure
     70   list.)
     71*/
     72#define VFP_MAGIC               0x56465001
     73#define IWMMXT_MAGIC            0x12ef842a
     74#define CRUNCH_MAGIC            0x5065cf03
     75
     76
     77struct user_vfp {
     78        unsigned long long fpregs[32];
     79        unsigned long fpscr;
     80};
     81
     82struct user_vfp *
     83find_vfp_info(ExceptionInformation *xp)
     84{
     85  char *p = (char *)(xp->uc_regspace);
     86  unsigned *q, magic;
     87
     88  while (1) {
     89    q = (unsigned *)p;                       
     90    magic = *q;
     91    if (magic == VFP_MAGIC) {
     92      return (struct user_vfp *)(q+2);
     93    }
     94    if ((magic == CRUNCH_MAGIC) ||
     95        (magic == IWMMXT_MAGIC)) {
     96      p += q[1];
     97    }
     98    else {
     99      return NULL;
     100    }
     101  }
     102}
     103
     104#endif
    56105#endif
    57106
     
    743792      show_lisp_register(xp, "temp1/fname/next_method_context", temp1);
    744793      show_lisp_register(xp, "temp2/nfn", temp2);
     794#ifdef LINUX
     795      {
     796        LispObj *nvrs = (LispObj *)find_vfp_info(xp);
     797
     798        if (nvrs != NULL) {
     799          int r;
     800
     801          for(r=save0;r<=save3;r++) {
     802            fprintf(dbgout,"s%02d (save%d) = %s\n",r,r-save0,print_lisp_object(nvrs[r]));
     803          }
     804        }
     805      }
     806#endif
    745807    }
    746808#endif
     
    10511113            b, xpGPR(xp, b));
    10521114  }
     1115#ifdef LINUX
     1116  {
     1117    LispObj *nvrs = (LispObj *)find_vfp_info(xp);
     1118   
     1119    if (nvrs != NULL) {
     1120      for(a=save0,b=save2;a<save2;a++,b++) {
     1121        fprintf(dbgout,"s%02d = 0x%08lX    s%02d = 0x%08lX\n",
     1122                a, nvrs[a], b, nvrs[b]);
     1123      }
     1124    }
     1125  }
     1126#endif
    10531127#endif
    10541128
     
    10561130}
    10571131
    1058 #ifdef ARM
    1059 #ifdef LINUX
    1060 
    1061 /* This stuff is buried in kernel headers.  Why ? */
    1062 
    1063 /* The uc_regspace field of a ucontext can contain coprocessor
    1064    info in structures whose first word is one of these magic
    1065    values; the structure list is terminated by something that's
    1066    not one of these magic values.
    1067 
    1068    Good thinking! That'll make the mechanism easy to extend!
    1069    (In practice, a word of 0 seems to terminate the structure
    1070    list.)
    1071 */
    1072 #define VFP_MAGIC               0x56465001
    1073 #define IWMMXT_MAGIC            0x12ef842a
    1074 #define CRUNCH_MAGIC            0x5065cf03
    1075 
    1076 
    1077 struct user_vfp {
    1078         unsigned long long fpregs[32];
    1079         unsigned long fpscr;
    1080 };
    1081 
    1082 struct user_vfp *
    1083 find_vfp_info(ExceptionInformation *xp)
    1084 {
    1085   char *p = (char *)(xp->uc_regspace);
    1086   unsigned *q, magic;
    1087 
    1088   while (1) {
    1089     q = (unsigned *)p;                       
    1090     magic = *q;
    1091     if (magic == VFP_MAGIC) {
    1092       return (struct user_vfp *)(q+2);
    1093     }
    1094     if ((magic == CRUNCH_MAGIC) ||
    1095         (magic == IWMMXT_MAGIC)) {
    1096       p += q[1];
    1097     }
    1098     else {
    1099       return NULL;
    1100     }
    1101   }
    1102 }
    1103 
    1104 #endif
    1105 #endif
    11061132
    11071133debug_command_return
     
    12031229    int dn,fn;
    12041230
    1205     for (dn=0,fn=0;dn<16;dn++) {
     1231
     1232    for (dn=0,fn=0;dn<14;dn++) { /* d14/d15 (s28-s31) contain lisp values */
    12061233      fprintf(dbgout, "s%02d = %10e (0x%08x)        s%02d = %10e (0x%08x)\n",fn,fp[fn],up[fn],fn+1,fp[fn+1],up[fn+1]);
    12071234      fn+=2;
Note: See TracChangeset for help on using the changeset viewer.