1 /* src/vm/jit/powerpc/patcher.c - PowerPC code patching functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Christian Thalinger
31 $Id: patcher.c 3572 2005-11-04 17:49:54Z twisti $
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/resolve.h"
46 #include "vm/references.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/patcher.h"
51 /* patcher_get_putstatic *******************************************************
55 <patched call position>
56 816dffc8 lwz r11,-56(r13)
57 80ab0000 lwz r5,0(r11)
59 *******************************************************************************/
61 bool patcher_get_putstatic(u1 *sp)
71 /* get stuff from the stack */
73 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
74 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
75 mcode = *((u4 *) (sp + 3 * 4));
76 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
77 disp = *((s4 *) (sp + 1 * 4));
78 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
82 /* get the fieldinfo */
84 if (!(fi = resolve_field_eager(uf))) {
90 /* check if the field's class is initialized */
92 if (!fi->class->initialized) {
93 if (!initialize_class(fi->class)) {
100 /* patch back original code */
102 *((u4 *) ra) = mcode;
104 /* synchronize instruction cache */
106 asm_cacheflush(ra, 4);
108 /* patch the field value's address */
110 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
112 PATCHER_MARK_PATCHED_MONITOREXIT;
118 /* patcher_get_putfield ********************************************************
122 <patched call position>
123 811f0014 lwz r8,20(r31)
125 *******************************************************************************/
127 bool patcher_get_putfield(u1 *sp)
130 java_objectheader *o;
132 unresolved_field *uf;
136 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
137 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
138 mcode = *((u4 *) (sp + 3 * 4));
139 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
140 pv = (u1 *) *((ptrint *) (sp + 1 * 4));
142 PATCHER_MONITORENTER;
144 /* get the fieldinfo */
146 if (!(fi = resolve_field_eager(uf))) {
152 /* patch back original code */
154 *((u4 *) ra) = mcode;
156 /* if we show disassembly, we have to skip the nop */
158 if (opt_showdisassemble)
161 /* patch the field's offset */
163 if (fi->type == TYPE_LNG) {
164 /* if the field has type long, we have to patch two instructions */
166 *((u4 *) ra) |= (s2) ((fi->offset + 4) & 0x0000ffff);
167 *((u4 *) (ra + 4)) |= (s2) (fi->offset & 0x0000ffff);
170 *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
173 /* synchronize instruction cache */
175 asm_cacheflush(ra, 8);
177 PATCHER_MARK_PATCHED_MONITOREXIT;
183 /* patcher_builtin_new *********************************************************
187 806dffc4 lwz r3,-60(r13)
188 <patched call postition>
189 81adffc0 lwz r13,-64(r13)
193 NOTICE: Only the displacement for the function address is passed,
194 but the address of the classinfo pointer is one below (above, in
195 addresses speaking). This is for sure.
197 *******************************************************************************/
199 bool patcher_builtin_new(u1 *sp)
202 java_objectheader *o;
204 constant_classref *cr;
209 /* get stuff from the stack */
211 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
212 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
213 mcode = *((u4 *) (sp + 3 * 4));
214 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
215 disp = *((s4 *) (sp + 1 * 4));
216 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
218 /* calculate and set the new return address */
221 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
223 PATCHER_MONITORENTER;
225 /* get the classinfo */
227 if (!(c = resolve_classref_eager_nonabstract(cr))) {
233 /* patch back original code */
235 *((u4 *) (ra + 4)) = mcode;
237 /* synchronize instruction cache */
239 asm_cacheflush(ra + 4, 4);
241 /* patch the classinfo pointer */
243 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
245 /* patch new function address */
247 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_new;
249 PATCHER_MARK_PATCHED_MONITOREXIT;
255 /* patcher_builtin_newarray ****************************************************
259 808dffc8 lwz r4,-56(r13)
260 <patched call position>
261 81adffc4 lwz r13,-60(r13)
265 NOTICE: Only the displacement for the function address is passed,
266 but the address of the vftbl pointer is one below (above, in
267 addresses speaking). This is for sure.
269 *******************************************************************************/
271 bool patcher_builtin_newarray(u1 *sp)
274 java_objectheader *o;
276 constant_classref *cr;
281 /* get stuff from the stack */
283 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
284 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
285 mcode = *((u4 *) (sp + 3 * 4));
286 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
287 disp = *((s4 *) (sp + 1 * 4));
288 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
290 /* calculate and set the new return address */
293 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
295 PATCHER_MONITORENTER;
297 /* get the classinfo */
299 if (!(c = resolve_classref_eager(cr))) {
305 /* patch back original code */
307 *((u4 *) (ra + 4)) = mcode;
309 /* synchronize instruction cache */
311 asm_cacheflush(ra + 4, 4);
313 /* patch the classinfo pointer */
315 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
317 /* patch new function address */
319 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_newarray;
321 PATCHER_MARK_PATCHED_MONITOREXIT;
327 /* patcher_builtin_multianewarray **********************************************
331 <patched call position>
332 808dffc0 lwz r4,-64(r13)
333 38a10038 addi r5,r1,56
334 81adffbc lwz r13,-68(r13)
338 *******************************************************************************/
340 bool patcher_builtin_multianewarray(u1 *sp)
343 java_objectheader *o;
345 constant_classref *cr;
350 /* get stuff from the stack */
352 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
353 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
354 mcode = *((u4 *) (sp + 3 * 4));
355 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
356 disp = *((s4 *) (sp + 1 * 4));
357 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
359 PATCHER_MONITORENTER;
361 /* get the classinfo */
363 if (!(c = resolve_classref_eager(cr))) {
369 /* patch back original code */
371 *((u4 *) ra) = mcode;
373 /* synchronize instruction cache */
375 asm_cacheflush(ra, 4);
377 /* patch the classinfo pointer */
379 *((ptrint *) (pv + disp)) = (ptrint) c;
381 PATCHER_MARK_PATCHED_MONITOREXIT;
387 /* patcher_builtin_arraycheckcast **********************************************
391 <patched call position>
392 808dffd8 lwz r4,-40(r13)
393 81adffd4 lwz r13,-44(r13)
397 NOTICE: Only the displacement of the vftbl pointer address is
398 passed, but the address of the function pointer is one above
399 (below, in addresses speaking). This is for sure.
401 *******************************************************************************/
403 bool patcher_builtin_arraycheckcast(u1 *sp)
406 java_objectheader *o;
408 constant_classref *cr;
413 /* get stuff from the stack */
415 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
416 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
417 mcode = *((u4 *) (sp + 3 * 4));
418 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
419 disp = *((s4 *) (sp + 1 * 4));
420 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
422 PATCHER_MONITORENTER;
424 /* get the classinfo */
426 if (!(c = resolve_classref_eager(cr))) {
432 /* patch back original code */
434 *((u4 *) ra) = mcode;
436 /* synchronize instruction cache */
438 asm_cacheflush(ra, 4);
440 /* patch the classinfo pointer */
442 *((ptrint *) (pv + disp)) = (ptrint) c;
444 /* patch new function address */
446 *((ptrint *) (pv + (disp - SIZEOF_VOID_P))) =
447 (ptrint) BUILTIN_arraycheckcast;
449 PATCHER_MARK_PATCHED_MONITOREXIT;
455 /* patcher_builtin_arrayinstanceof *********************************************
459 808dff50 lwz r4,-176(r13)
460 <patched call position>
461 81adff4c lwz r13,-180(r13)
465 NOTICE: Only the displacement for the function address is passed,
466 but the address of the vftbl pointer is one below (above, in
467 addresses speaking). This is for sure.
469 *******************************************************************************/
471 bool patcher_builtin_arrayinstanceof(u1 *sp)
474 java_objectheader *o;
476 constant_classref *cr;
481 /* get stuff from the stack */
483 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
484 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
485 mcode = *((u4 *) (sp + 3 * 4));
486 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
487 disp = *((s4 *) (sp + 1 * 4));
488 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
490 /* calculate and set the new return address */
493 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
495 PATCHER_MONITORENTER;
497 /* get the classinfo */
499 if (!(c = resolve_classref_eager(cr))) {
505 /* patch back original code */
507 *((u4 *) (ra + 4)) = mcode;
509 /* synchronize instruction cache */
511 asm_cacheflush(ra + 4, 4);
513 /* patch the classinfo pointer */
515 *((ptrint *) (pv + (disp + SIZEOF_VOID_P))) = (ptrint) c;
517 /* patch new function address */
519 *((ptrint *) (pv + disp)) = (ptrint) BUILTIN_arrayinstanceof;
521 PATCHER_MARK_PATCHED_MONITOREXIT;
527 /* patcher_invokestatic_special ************************************************
531 <patched call position>
532 81adffd8 lwz r13,-40(r13)
536 ******************************************************************************/
538 bool patcher_invokestatic_special(u1 *sp)
541 java_objectheader *o;
543 unresolved_method *um;
548 /* get stuff from the stack */
550 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
551 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
552 mcode = *((u4 *) (sp + 3 * 4));
553 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
554 disp = *((s4 *) (sp + 1 * 4));
555 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
557 PATCHER_MONITORENTER;
559 /* get the fieldinfo */
561 if (!(m = resolve_method_eager(um))) {
567 /* patch back original code */
569 *((u4 *) ra) = mcode;
571 /* synchronize instruction cache */
573 asm_cacheflush(ra, 4);
575 /* patch stubroutine */
577 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
579 PATCHER_MARK_PATCHED_MONITOREXIT;
585 /* patcher_invokevirtual *******************************************************
589 <patched call position>
590 81830000 lwz r12,0(r3)
591 81ac0088 lwz r13,136(r12)
595 *******************************************************************************/
597 bool patcher_invokevirtual(u1 *sp)
600 java_objectheader *o;
602 unresolved_method *um;
605 /* get stuff from the stack */
607 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
608 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
609 mcode = *((u4 *) (sp + 3 * 4));
610 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
612 PATCHER_MONITORENTER;
614 /* get the fieldinfo */
616 if (!(m = resolve_method_eager(um))) {
622 /* patch back original code */
624 *((u4 *) ra) = mcode;
626 /* if we show disassembly, we have to skip the nop */
628 if (opt_showdisassemble)
631 /* patch vftbl index */
633 *((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
634 sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
636 /* synchronize instruction cache */
638 asm_cacheflush(ra, 2 * 4);
640 PATCHER_MARK_PATCHED_MONITOREXIT;
646 /* patcher_invokeinterface *****************************************************
650 <patched call position>
651 81830000 lwz r12,0(r3)
652 818cffd0 lwz r12,-48(r12)
653 81ac000c lwz r13,12(r12)
657 *******************************************************************************/
659 bool patcher_invokeinterface(u1 *sp)
662 java_objectheader *o;
664 unresolved_method *um;
667 /* get stuff from the stack */
669 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
670 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
671 mcode = *((u4 *) (sp + 3 * 4));
672 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
674 PATCHER_MONITORENTER;
676 /* get the fieldinfo */
678 if (!(m = resolve_method_eager(um))) {
684 /* patch back original code */
686 *((u4 *) ra) = mcode;
688 /* if we show disassembly, we have to skip the nop */
690 if (opt_showdisassemble)
693 /* patch interfacetable index */
695 *((s4 *) (ra + 1 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
696 sizeof(methodptr*) * m->class->index) & 0x0000ffff);
698 /* patch method offset */
700 *((s4 *) (ra + 2 * 4)) |=
701 (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
703 /* synchronize instruction cache */
705 asm_cacheflush(ra, 3 * 4);
707 PATCHER_MARK_PATCHED_MONITOREXIT;
713 /* patcher_checkcast_instanceof_flags ******************************************
717 <patched call position>
718 818dff7c lwz r12,-132(r13)
720 *******************************************************************************/
722 bool patcher_checkcast_instanceof_flags(u1 *sp)
725 java_objectheader *o;
727 constant_classref *cr;
732 /* get stuff from the stack */
734 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
735 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
736 mcode = *((u4 *) (sp + 3 * 4));
737 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
738 disp = *((s4 *) (sp + 1 * 4));
739 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
741 PATCHER_MONITORENTER;
743 /* get the fieldinfo */
745 if (!(c = resolve_classref_eager(cr))) {
751 /* patch back original code */
753 *((u4 *) ra) = mcode;
755 /* synchronize instruction cache */
757 asm_cacheflush(ra, 4);
759 /* patch class flags */
761 *((s4 *) (pv + disp)) = (s4) c->flags;
763 PATCHER_MARK_PATCHED_MONITOREXIT;
769 /* patcher_checkcast_instanceof_interface **************************************
773 <patched call position>
774 81870000 lwz r12,0(r7)
775 800c0010 lwz r0,16(r12)
776 34000000 addic. r0,r0,0
777 408101fc ble- 0x3002e518
778 800c0000 lwz r0,0(r12)
780 *******************************************************************************/
782 bool patcher_checkcast_instanceof_interface(u1 *sp)
785 java_objectheader *o;
787 constant_classref *cr;
790 /* get stuff from the stack */
792 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
793 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
794 mcode = *((u4 *) (sp + 3 * 4));
795 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
797 PATCHER_MONITORENTER;
799 /* get the fieldinfo */
801 if (!(c = resolve_classref_eager(cr))) {
807 /* patch back original code */
809 *((u4 *) ra) = mcode;
811 /* if we show disassembly, we have to skip the nop */
813 if (opt_showdisassemble)
816 /* patch super class index */
818 *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
820 *((s4 *) (ra + 4 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
821 c->index * sizeof(methodptr*)) & 0x0000ffff);
823 /* synchronize instruction cache */
825 asm_cacheflush(ra, 5 * 4);
827 PATCHER_MARK_PATCHED_MONITOREXIT;
833 /* patcher_checkcast_class *****************************************************
837 <patched call position>
838 81870000 lwz r12,0(r7)
839 800c0014 lwz r0,20(r12)
840 818dff78 lwz r12,-136(r13)
842 *******************************************************************************/
844 bool patcher_checkcast_class(u1 *sp)
847 java_objectheader *o;
849 constant_classref *cr;
854 /* get stuff from the stack */
856 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
857 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
858 mcode = *((u4 *) (sp + 3 * 4));
859 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
860 disp = *((s4 *) (sp + 1 * 4));
861 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
863 PATCHER_MONITORENTER;
865 /* get the fieldinfo */
867 if (!(c = resolve_classref_eager(cr))) {
873 /* patch back original code */
875 *((u4 *) ra) = mcode;
877 /* synchronize instruction cache */
879 asm_cacheflush(ra, 4);
881 /* patch super class' vftbl */
883 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
885 PATCHER_MARK_PATCHED_MONITOREXIT;
891 /* patcher_instanceof_class ****************************************************
895 <patched call position>
896 817d0000 lwz r11,0(r29)
897 818dff8c lwz r12,-116(r13)
899 *******************************************************************************/
901 bool patcher_instanceof_class(u1 *sp)
904 java_objectheader *o;
906 constant_classref *cr;
911 /* get stuff from the stack */
913 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
914 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
915 mcode = *((u4 *) (sp + 3 * 4));
916 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
917 disp = *((s4 *) (sp + 1 * 4));
918 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
920 PATCHER_MONITORENTER;
922 /* get the fieldinfo */
924 if (!(c = resolve_classref_eager(cr))) {
930 /* patch back original code */
932 *((u4 *) ra) = mcode;
934 /* synchronize instruction cache */
936 asm_cacheflush(ra, 4);
938 /* patch super class' vftbl */
940 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
942 PATCHER_MARK_PATCHED_MONITOREXIT;
948 /* patcher_clinit **************************************************************
952 *******************************************************************************/
954 bool patcher_clinit(u1 *sp)
957 java_objectheader *o;
961 /* get stuff from the stack */
963 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
964 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
965 mcode = *((u4 *) (sp + 3 * 4));
966 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
968 PATCHER_MONITORENTER;
970 /* check if the class is initialized */
972 if (!c->initialized) {
973 if (!initialize_class(c)) {
980 /* patch back original code */
982 *((u4 *) ra) = mcode;
984 /* synchronize instruction cache */
986 asm_cacheflush(ra, 4);
988 PATCHER_MARK_PATCHED_MONITOREXIT;
994 /* patcher_athrow_areturn ******************************************************
998 <patched call position>
1000 *******************************************************************************/
1002 bool patcher_athrow_areturn(u1 *sp)
1005 java_objectheader *o;
1007 unresolved_class *uc;
1010 /* get stuff from the stack */
1012 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
1013 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
1014 mcode = *((u4 *) (sp + 3 * 4));
1015 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
1017 PATCHER_MONITORENTER;
1019 /* resolve the class */
1021 if (!resolve_class(uc, resolveEager, false, &c)) {
1022 PATCHER_MONITOREXIT;
1027 /* patch back original code */
1029 *((u4 *) ra) = mcode;
1031 /* synchronize instruction cache */
1033 asm_cacheflush(ra, 4);
1035 PATCHER_MARK_PATCHED_MONITOREXIT;
1041 /* patcher_resolve_native ******************************************************
1045 *******************************************************************************/
1047 #if !defined(ENABLE_STATICVM)
1048 bool patcher_resolve_native(u1 *sp)
1051 java_objectheader *o;
1058 /* get stuff from the stack */
1060 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
1061 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
1062 mcode = *((u4 *) (sp + 3 * 4));
1063 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
1064 disp = *((s4 *) (sp + 1 * 4));
1065 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
1067 /* calculate and set the new return address */
1070 *((ptrint *) (sp + 5 * 4)) = (ptrint) ra;
1072 PATCHER_MONITORENTER;
1074 /* resolve native function */
1076 if (!(f = native_resolve_function(m))) {
1077 PATCHER_MONITOREXIT;
1082 /* patch back original code */
1084 *((u4 *) ra) = mcode;
1086 /* synchronize instruction cache */
1088 asm_cacheflush(ra, 4);
1090 /* patch native function pointer */
1092 *((ptrint *) (pv + disp)) = (ptrint) f;
1094 PATCHER_MARK_PATCHED_MONITOREXIT;
1098 #endif /* !defined(ENABLE_STATICVM) */
1102 * These are local overrides for various environment variables in Emacs.
1103 * Please do not remove this and leave it at the end of the file, where
1104 * Emacs will automagically detect them.
1105 * ---------------------------------------------------------------------
1108 * indent-tabs-mode: t
1112 * vim:noexpandtab:sw=4:ts=4: