├── Makefile.in ├── autoconf ├── config.guess ├── config.sub └── install-sh ├── config.h.in ├── configure.in ├── lirasm ├── LInsClasses.tbl ├── lirasm.cpp ├── testlirc.sh └── tests │ ├── 32-bit │ ├── many_params.in │ └── many_params.out │ ├── 64-bit │ ├── dasq.in │ ├── dasq.out │ ├── qasd.in │ ├── qasd.out │ ├── shq.in │ └── shq.out │ ├── add.in │ ├── add.out │ ├── addd.in │ ├── addd.out │ ├── addjovi.in │ ├── addjovi.out │ ├── addjovi_ovf.in │ ├── addjovi_ovf.out │ ├── addsub.in │ ├── addsub.out │ ├── bigendian │ ├── fuzz-527178.in │ ├── fuzz-527178.out │ ├── ldc2i.in │ ├── ldc2i.out │ ├── lds2i.in │ ├── lds2i.out │ ├── lduc2ui.in │ ├── lduc2ui.out │ ├── ldus2ui.in │ └── ldus2ui.out │ ├── bug596923.in │ ├── bug596923.out │ ├── call1.in │ ├── call1.out │ ├── call2.in │ ├── call2.out │ ├── calld1.in │ ├── calld1.out │ ├── callid1.in │ ├── callid1.out │ ├── callid2.in │ ├── callid2.out │ ├── callid3.in │ ├── callid3.out │ ├── callv.in │ ├── callv.out │ ├── cmov.in │ ├── cmov.out │ ├── cond_eqd.in │ ├── cond_eqd.out │ ├── cond_eqi.in │ ├── cond_eqi.out │ ├── cond_ged.in │ ├── cond_ged.out │ ├── cond_gei.in │ ├── cond_gei.out │ ├── cond_geui.in │ ├── cond_geui.out │ ├── cond_gtd.in │ ├── cond_gtd.out │ ├── cond_gti.in │ ├── cond_gti.out │ ├── cond_gtui.in │ ├── cond_gtui.out │ ├── cond_led.in │ ├── cond_led.out │ ├── cond_lei.in │ ├── cond_lei.out │ ├── cond_leui.in │ ├── cond_leui.out │ ├── cond_ltd.in │ ├── cond_ltd.out │ ├── cond_lti.in │ ├── cond_lti.out │ ├── cond_ltui.in │ ├── cond_ltui.out │ ├── divd.in │ ├── divd.out │ ├── float_double.in │ ├── float_double.out │ ├── floatingpoint.in │ ├── floatingpoint.out │ ├── fneg.in │ ├── fneg.out │ ├── fpu1-598151.in │ ├── fpu1-598151.out │ ├── fpu2-598151.in │ ├── fpu2-598151.out │ ├── hardfloat │ ├── d2i.in │ ├── d2i.out │ ├── f2i.in │ ├── f2i.out │ ├── i2d.in │ ├── i2d.out │ ├── ui2d.in │ └── ui2d.out │ ├── littleendian │ ├── fuzz-527178.in │ ├── fuzz-527178.out │ ├── ldc2i.in │ ├── ldc2i.out │ ├── lds2i.in │ ├── lds2i.out │ ├── lduc2ui.in │ ├── lduc2ui.out │ ├── ldus2ui.in │ └── ldus2ui.out │ ├── loadstore.in │ ├── loadstore.out │ ├── mul_xxx.in │ ├── mul_xxx.out │ ├── mul_xxy.in │ ├── mul_xxy.out │ ├── mul_xyy.in │ ├── mul_xyy.out │ ├── mul_xyz.in │ ├── mul_xyz.out │ ├── muld.in │ ├── muld.out │ ├── muljovi.in │ ├── muljovi.out │ ├── muljovi_ovf.in │ ├── muljovi_ovf.out │ ├── muljovi_xxx.in │ ├── muljovi_xxx.out │ ├── muljovi_xxy.in │ ├── muljovi_xxy.out │ ├── muljovi_xyy.in │ ├── muljovi_xyy.out │ ├── muljovi_xyz.in │ ├── muljovi_xyz.out │ ├── mulov_xxx.in │ ├── mulov_xxx.out │ ├── mulov_xxy.in │ ├── mulov_xxy.out │ ├── mulov_xyy.in │ ├── mulov_xyy.out │ ├── mulov_xyz.in │ ├── mulov_xyz.out │ ├── multfrag1.in │ ├── multfrag1.out │ ├── multfrag2.in │ ├── multfrag2.out │ ├── multfrag3.in │ ├── multfrag3.out │ ├── negnot.in │ ├── negnot.out │ ├── random.out │ ├── shi.in │ ├── shi.out │ ├── softfloat │ ├── dhi2i.in │ ├── dhi2i.out │ ├── dlo2i.in │ ├── dlo2i.out │ ├── ii2d.in │ └── ii2d.out │ ├── std2f.in │ ├── std2f.out │ ├── subd.in │ ├── subd.out │ ├── subjovi.in │ ├── subjovi.out │ ├── subjovi_ovf.in │ └── subjovi_ovf.out ├── nanojit ├── Allocator.cpp ├── Allocator.h ├── Assembler.cpp ├── Assembler.h ├── CodeAlloc.cpp ├── CodeAlloc.h ├── Containers.cpp ├── Containers.h ├── Fragmento.cpp ├── Fragmento.h ├── LIR.cpp ├── LIR.h ├── LIRopcode.tbl ├── Native.h ├── NativeARM.cpp ├── NativeARM.h ├── NativeCommon.h ├── NativeMIPS.cpp ├── NativeMIPS.h ├── NativePPC.cpp ├── NativePPC.h ├── NativeSH4-auto-generated.h ├── NativeSH4.cpp ├── NativeSH4.h ├── NativeSparc.cpp ├── NativeSparc.h ├── NativeX64.cpp ├── NativeX64.h ├── Nativei386.cpp ├── Nativei386.h ├── RegAlloc.cpp ├── RegAlloc.h ├── VMPI.cpp ├── VMPI.h ├── avmplus.cpp ├── avmplus.h ├── manifest.mk ├── nanojit.h ├── njconfig.cpp ├── njconfig.h └── njcpudetect.h └── vprof ├── manifest.mk ├── readme.txt ├── testVprofMT.c ├── vprof.cpp └── vprof.h /Makefile.in: -------------------------------------------------------------------------------- 1 | # -*- Mode: makefile -*- 2 | # 3 | # ***** BEGIN LICENSE BLOCK ***** 4 | # Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | # 6 | # The contents of this file are subject to the Mozilla Public License Version 7 | # 1.1 (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # http://www.mozilla.org/MPL/ 10 | # 11 | # Software distributed under the License is distributed on an "AS IS" basis, 12 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | # for the specific language governing rights and limitations under the 14 | # License. 15 | # 16 | # The Original Code is Nanojit Build System. 17 | # 18 | # The Initial Developer of the Original Code is Mozilla Corporation. 19 | # Portions created by the Initial Developer are Copyright (C) 2009 20 | # the Initial Developer. All Rights Reserved. 21 | # 22 | # Contributor(s): 23 | # Graydon Hoare 24 | # 25 | # Alternatively, the contents of this file may be used under the terms of 26 | # either of the GNU General Public License Version 2 or later (the "GPL"), 27 | # or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | # in which case the provisions of the GPL or the LGPL are applicable instead 29 | # of those above. If you wish to allow use of your version of this file only 30 | # under the terms of either the GPL or the LGPL, and not to allow others to 31 | # use your version of this file under the terms of the MPL, indicate your 32 | # decision by deleting the provisions above and replace them with the notice 33 | # and other provisions required by the GPL or the LGPL. If you do not delete 34 | # the provisions above, a recipient may use your version of this file under 35 | # the terms of any one of the MPL, the GPL or the LGPL. 36 | # 37 | # ***** END LICENSE BLOCK ***** 38 | 39 | ################## 40 | # autoconf imports 41 | ################## 42 | 43 | CC := @CC@ 44 | CXX := @CXX@ 45 | GNU_CC := @GNU_CC@ 46 | LD := @LD@ 47 | NANOJIT_ARCH := @NANOJIT_ARCH@ 48 | DEFS := @DEFS@ -DNANOJIT_CENTRAL 49 | srcdir := @srcdir@ 50 | CFLAGS := @CFLAGS@ 51 | LDFLAGS := @LDFLAGS@ 52 | CXXFLAGS := @CXXFLAGS@ 53 | WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@ 54 | EXE_SUFFIX := @EXE_SUFFIX@ 55 | OBJ_SUFFIX := @OBJ_SUFFIX@ 56 | 57 | # NB: delayed substitution on this one. 58 | LINK = @LINK@ 59 | 60 | ####################### 61 | # normal GNU make rules 62 | ####################### 63 | 64 | VPATH = $(srcdir) \ 65 | $(srcdir)/nanojit \ 66 | $(srcdir)/vprof \ 67 | $(srcdir)/lirasm \ 68 | $(srcdir)/lirasm/tests 69 | 70 | NATIVE_SRC=Native$(NANOJIT_ARCH).cpp 71 | OTHER_SRCS=Allocator.cpp \ 72 | Assembler.cpp \ 73 | avmplus.cpp \ 74 | CodeAlloc.cpp \ 75 | Containers.cpp \ 76 | Fragmento.cpp \ 77 | LIR.cpp \ 78 | lirasm.cpp \ 79 | njconfig.cpp \ 80 | RegAlloc.cpp \ 81 | VMPI.cpp \ 82 | vprof.cpp 83 | 84 | 85 | SRCS := $(OTHER_SRCS) $(NATIVE_SRC) 86 | HDRS := $(wildcard $(srcdir)/nanojit/*.h) 87 | INS := $(wildcard $(srcdir)/lirasm/tests/*.in) 88 | 89 | OBJS := $(notdir $(SRCS:.cpp=$(OBJ_SUFFIX))) 90 | OUTS := $(filter-out random.out random-opt.out, $(notdir $(INS:.in=.out))) 91 | 92 | LIRASM := bin/lirasm$(EXE_SUFFIX) 93 | 94 | CPPFLAGS += $(DEFS) 95 | CPPFLAGS += -I. -I$(srcdir) -I$(srcdir)/nanojit 96 | 97 | ############# 98 | # Build rules 99 | ############# 100 | 101 | $(LIRASM): $(OBJS) 102 | mkdir -p $(dir $(LIRASM)) 103 | $(call LINK,$@) $(OBJS) 104 | chmod 0755 $(LIRASM) 105 | 106 | %$(OBJ_SUFFIX): %.cpp $(HDRS) Makefile 107 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(WARNINGS_AS_ERRORS) -c $< 108 | 109 | 110 | ############ 111 | # Test rules 112 | ############ 113 | 114 | .PHONY: check 115 | 116 | check: $(LIRASM) $(OUTS) 117 | $(srcdir)/lirasm/testlirc.sh $(LIRASM) 118 | 119 | 120 | ################### 121 | # Reconfigury rules 122 | ################### 123 | 124 | $(srcdir)/configure: configure.in 125 | cd $(srcdir) && autoconf 126 | 127 | Makefile: configure Makefile.in 128 | $< 129 | -------------------------------------------------------------------------------- /autoconf/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # install - install a program, script, or datafile 5 | # This comes from X11R5; it is not part of GNU. 6 | # 7 | # $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ 8 | # 9 | # This script is compatible with the BSD install script, but was written 10 | # from scratch. 11 | # 12 | 13 | 14 | # set DOITPROG to echo to test this script 15 | 16 | # Don't use :- since 4.3BSD and earlier shells don't like it. 17 | doit="${DOITPROG-}" 18 | 19 | 20 | # put in absolute paths if you don't have them in your path; or use env. vars. 21 | 22 | mvprog="${MVPROG-mv}" 23 | cpprog="${CPPROG-cp}" 24 | chmodprog="${CHMODPROG-chmod}" 25 | chownprog="${CHOWNPROG-chown}" 26 | chgrpprog="${CHGRPPROG-chgrp}" 27 | stripprog="${STRIPPROG-strip}" 28 | rmprog="${RMPROG-rm}" 29 | 30 | instcmd="$mvprog" 31 | chmodcmd="" 32 | chowncmd="" 33 | chgrpcmd="" 34 | stripcmd="" 35 | rmcmd="$rmprog -f" 36 | mvcmd="$mvprog" 37 | src="" 38 | dst="" 39 | 40 | while [ x"$1" != x ]; do 41 | case $1 in 42 | -c) instcmd="$cpprog" 43 | shift 44 | continue;; 45 | 46 | -m) chmodcmd="$chmodprog $2" 47 | shift 48 | shift 49 | continue;; 50 | 51 | -o) chowncmd="$chownprog $2" 52 | shift 53 | shift 54 | continue;; 55 | 56 | -g) chgrpcmd="$chgrpprog $2" 57 | shift 58 | shift 59 | continue;; 60 | 61 | -s) stripcmd="$stripprog" 62 | shift 63 | continue;; 64 | 65 | *) if [ x"$src" = x ] 66 | then 67 | src=$1 68 | else 69 | dst=$1 70 | fi 71 | shift 72 | continue;; 73 | esac 74 | done 75 | 76 | if [ x"$src" = x ] 77 | then 78 | echo "install: no input file specified" 79 | exit 1 80 | fi 81 | 82 | if [ x"$dst" = x ] 83 | then 84 | echo "install: no destination specified" 85 | exit 1 86 | fi 87 | 88 | 89 | # If destination is a directory, append the input filename; if your system 90 | # does not like double slashes in filenames, you may need to add some logic 91 | 92 | if [ -d $dst ] 93 | then 94 | dst="$dst"/`basename $src` 95 | fi 96 | 97 | # Make a temp file name in the proper directory. 98 | 99 | dstdir=`dirname $dst` 100 | dsttmp=$dstdir/#inst.$$# 101 | 102 | # Move or copy the file name to the temp name 103 | 104 | $doit $instcmd $src $dsttmp 105 | 106 | # and set any options; do chmod last to preserve setuid bits 107 | 108 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi 109 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi 110 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi 111 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi 112 | 113 | # Now rename the file to the real destination. 114 | 115 | $doit $rmcmd $dst 116 | $doit $mvcmd $dsttmp $dst 117 | 118 | 119 | exit 0 120 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | 2 | #undef DEBUG 3 | #undef AVMPLUS_AMD64 4 | #undef AVMPLUS_64BIT 5 | #undef AVMPLUS_ARM 6 | #undef AVMPLUS_IA32 7 | #undef AVMPLUS_LINUX 8 | #undef AVMPLUS_OS2 9 | #undef AVMPLUS_PPC 10 | #undef AVMPLUS_MIPS 11 | #undef VMCFG_SH4 12 | #undef AVMPLUS_SPARC 13 | #undef SOLARIS 14 | #undef AVMPLUS_UNIX 15 | #undef AVMPLUS_WIN32 16 | #undef FEATURE_NANOJIT 17 | #undef WINVER 18 | #undef _CRT_NONSTDC_NO_DEPRECATE 19 | #undef _CRT_NONSTDC_NO_WARNINGS 20 | #undef _CRT_SECURE_NO_DEPRECATE 21 | #undef _CRT_SECURE_NO_WARNINGS 22 | #undef WIN32 23 | #undef _WIN32_IE 24 | #undef _WIN32_WINNT 25 | -------------------------------------------------------------------------------- /lirasm/LInsClasses.tbl: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * vim: set ts=8 sw=4 et tw=0 ft=c: 3 | * 4 | * ***** BEGIN LICENSE BLOCK ***** 5 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 | * 7 | * The contents of this file are subject to the Mozilla Public License Version 8 | * 1.1 (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * http://www.mozilla.org/MPL/ 11 | * 12 | * Software distributed under the License is distributed on an "AS IS" basis, 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 | * for the specific language governing rights and limitations under the 15 | * License. 16 | * 17 | * The Original Code is SpiderMonkey nanojit. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * the Mozilla Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 2009 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * Nicholas Nethercote 26 | * 27 | * Alternatively, the contents of this file may be used under the terms of 28 | * either of the GNU General Public License Version 2 or later (the "GPL"), 29 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 | * in which case the provisions of the GPL or the LGPL are applicable instead 31 | * of those above. If you wish to allow use of your version of this file only 32 | * under the terms of either the GPL or the LGPL, and not to allow others to 33 | * use your version of this file under the terms of the MPL, indicate your 34 | * decision by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL or the LGPL. If you do not delete 36 | * the provisions above, a recipient may use your version of this file under 37 | * the terms of any one of the MPL, the GPL or the LGPL. 38 | * 39 | * ***** END LICENSE BLOCK ***** */ 40 | 41 | /* LIns classes, as required for --random mode. Includers must define a CL___ 42 | * macro of the following form: 43 | * 44 | * #define CL___(name, only64bit, relFreq) ... 45 | * 46 | * Selected arguments can be used within the macro expansions. 47 | * 48 | * Field Description 49 | * ----- ----------- 50 | * name Name of the instruction class. The types are B (boolean), I 51 | * (32-bit integer), Q (64-bit integer), F (64-bit float), N 52 | * (null). A name of the form LOP_Z_XY means that it takes 53 | * arguments of type X and Y and produces a result of type Z. 54 | * 55 | * relFreq We weight each class differently, so that some classes are more 56 | * common than others. This field gives the relative frequency of 57 | * the instruction class. All the relFreqs together can sum up to 58 | * any number, but it's easier to think about if the sum is a 59 | * round number. (That's why the relFreqs add up to 100%; the 60 | * running total is shown in comments.) The sum also shouldn't be 61 | * too big, as we generate a table with that many elements in it. 62 | * 63 | * Note that we want a decent number of value sinks (eg. 64 | * stores, calls, guards) and not too many value sources (eg. 65 | * immediates, loads) so that the amount of dead code generated is 66 | * reasonable. 67 | * 68 | * Because certain opcode classes aren't supported on all platforms, CLxyz must be one 69 | * of the following: 70 | * 71 | * CL___: for opcode classes supported on all platforms. 72 | * CL_64: for opcode classes supported only on 64-bit platforms. 73 | */ 74 | 75 | #ifdef NANOJIT_64BIT 76 | # define CL_64(a, b) CL___(a, b) 77 | #else 78 | # define CL_64(a, b) 79 | #endif 80 | 81 | 82 | CL___( LFENCE, 1) // 1% LIR_regfence, LIR_xbarrier 83 | 84 | CL___( LALLOC, 1) // 2% LIR_alloc 85 | 86 | CL___( LIMM_I, 4) // 6% LIR_imm 87 | CL_64( LIMM_Q, 3) // 9% LIR_quad 88 | CL___( LIMM_D, 3) // 12% LIR_float 89 | 90 | CL___( LOP_I_I, 2) // 14% LIR_neg, LIR_not 91 | CL_64( LOP_Q_Q, 0) // 14% (none) 92 | CL___( LOP_D_D, 2) // 16% LIR_fneg 93 | 94 | CL___( LOP_I_II, 6) // 32% LIR_add, LIR_and, LIR_eq, etc. 95 | CL_64( LOP_Q_QQ, 7) // 39% LIR_qiadd, LIR_qiand, LIR_qeq, etc. 96 | CL_64( LOP_Q_QI, 2) // 41% LIR_qilsh, LIR_qirsh, LIR_qursh 97 | CL___( LOP_D_DD, 0) // 51% LIR_fadd, etc. 98 | 99 | // cmov has a low weight because is also used with LIR_div/LIR_mod. 100 | CL___( LOP_I_BII, 1) // 52% LIR_cmovi 101 | CL_64( LOP_Q_BQQ, 1) // 53% LIR_cmovq 102 | CL___( LOP_D_BDD, 1) // 54% LIR_cmovd 103 | 104 | CL___( LOP_B_II, 3) // 57% LIR_eq, LIR_lt, etc 105 | CL_64( LOP_B_QQ, 3) // 60% LIR_qeq, LIR_qlt, etc 106 | CL___( LOP_B_DD, 3) // 63% LIR_feq, LIR_flt, etc 107 | 108 | CL_64( LOP_Q_I, 1) // 64% LIR_i2q, LIR_u2q 109 | CL___( LOP_D_I, 1) // 65% LIR_i2f, LIR_u2f 110 | CL_64( LOP_I_Q, 1) // 66% LIR_q2i 111 | CL___( LOP_I_D, 1) // 67% LIR_qlo, LIR_qhi, LIR_f2i 112 | CL_64( LOP_Q_D, 1) // 68% LIR_dasq 113 | CL_64( LOP_D_Q, 1) // 69% LIR_qasd 114 | CL___( LOP_D_II, 1) // 70% LIR_qjoin 115 | 116 | CL___( LLD_I, 3) // 73% LIR_ld, LIR_ldc, LIR_ld*b, LIR_ld*s 117 | CL_64( LLD_Q, 2) // 75% LIR_ldq, LIR_ldqc 118 | CL___( LLD_D, 3) // 78% LIR_ldf, LIR_ldfc 119 | 120 | CL___( LST_I, 5) // 83% LIR_sti 121 | CL_64( LST_Q, 4) // 87% LIR_stqi 122 | CL___( LST_D, 5) // 92% LIR_stfi 123 | 124 | CL___( LCALL_I_I1, 1) // 93% LIR_icall 125 | CL___( LCALL_I_I6, 1) // 94% LIR_icall 126 | CL_64( LCALL_Q_Q2, 1) // 95% LIR_qcall 127 | CL_64( LCALL_Q_Q7, 1) // 96% LIR_qcall 128 | CL___( LCALL_D_D3, 1) // 97% LIR_fcall 129 | CL___( LCALL_D_D8, 1) // 98% LIR_fcall 130 | CL_64( LCALL_V_IQD, 1) // 99% LIR_icall or LIR_qcall 131 | 132 | CL___( LLABEL, 1) //100% LIR_label 133 | 134 | 135 | #undef CL_64 136 | -------------------------------------------------------------------------------- /lirasm/testlirc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | exitcode=0 6 | 7 | LIRASM=$1 8 | 9 | TESTS_DIR=`dirname "$0"`/tests 10 | 11 | function runtest { 12 | local infile=$1 13 | local options=${2-} 14 | 15 | # Catch a request for the random tests. 16 | if [[ $infile == --random* ]] ; then 17 | local outfile=$TESTS_DIR/random.out 18 | else 19 | local outfile=`echo $infile | sed 's/\.in/\.out/'` 20 | fi 21 | 22 | if [[ ! -e "$outfile" ]] ; then 23 | echo "$0: error: no out file $outfile" 24 | exit 1 25 | fi 26 | 27 | # sed used to strip extra leading zeros from exponential values 'e+00' (see bug 602786) 28 | if $LIRASM $options --execute $infile | tr -d '\r' | sed -e 's/e+00*/e+0/g' > testoutput.txt && cmp -s testoutput.txt $outfile ; then 29 | echo "TEST-PASS | lirasm | lirasm $options --execute $infile" 30 | else 31 | echo "TEST-UNEXPECTED-FAIL | lirasm | lirasm $options --execute $infile" 32 | echo "expected output" 33 | cat $outfile 34 | echo "actual output" 35 | cat testoutput.txt 36 | exitcode=1 37 | fi 38 | } 39 | 40 | function runtests { 41 | local testdir=$1 42 | local options=${2-} 43 | for infile in "$TESTS_DIR"/"$testdir"/*.in ; do 44 | runtest $infile "$options" 45 | done 46 | } 47 | 48 | if [[ $($LIRASM --show-arch 2>/dev/null) == "i386" ]] ; then 49 | # i386 with SSE2. 50 | runtests "." 51 | runtests "hardfloat" 52 | runtests "32-bit" 53 | runtests "littleendian" 54 | runtest "--random 1000000" 55 | runtest "--random 1000000 --optimize" 56 | 57 | # i386 without SSE2. 58 | runtests "." "--nosse" 59 | runtests "hardfloat" "--nosse" 60 | runtests "32-bit" "--nosse" 61 | runtests "littleendian" "--nosse" 62 | runtest "--random 1000000" "--nosse" 63 | 64 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "X64" ]] ; then 65 | # X64. 66 | runtests "." 67 | runtests "hardfloat" 68 | runtests "64-bit" 69 | runtests "littleendian" 70 | runtest "--random 1000000" 71 | runtest "--random 1000000 --optimize" 72 | 73 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "arm" ]] ; then 74 | # ARMv7 with VFP. We could test without VFP but such a platform seems 75 | # unlikely. ARM is bi-endian but usually configured as little-endian. 76 | runtests "." 77 | runtests "hardfloat" 78 | runtests "32-bit" 79 | runtests "littleendian" 80 | runtest "--random 1000000" 81 | runtest "--random 1000000" "--optimize" 82 | 83 | # ARMv6 with VFP. ARMv6 without VFP doesn't seem worth testing. 84 | # Random tests are reduced. 85 | runtests "." "--arch 6" 86 | runtests "hardfloat" "--arch 6" 87 | runtests "32-bit" "--arch 6" 88 | runtests "littleendian" "--arch 6" 89 | runtest "--random 100000" "--arch 6" 90 | 91 | # ARMv5 without VFP. ARMv5 with VFP doesn't seem worth testing. 92 | # Random tests are reduced. 93 | runtests "." "--arch 5 --novfp" 94 | runtests "softfloat" "--arch 5 --novfp" 95 | runtests "32-bit" "--arch 5 --novfp" 96 | runtests "littleendian" "--arch 5 --novfp" 97 | runtest "--random 100000" "--arch 5 --novfp" 98 | 99 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "ppc" ]] ; then 100 | # PPC is bi-endian but usually configured as big-endian. 101 | runtests "." 102 | runtests "hardfloat" 103 | if [[ $($LIRASM --show-word-size) == "32" ]] ; then 104 | runtests "32-bit" 105 | else 106 | runtests "64-bit" 107 | fi 108 | runtests "bigendian" 109 | runtest "--random 1000000" 110 | runtest "--random 1000000 --optimize" 111 | 112 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "sparc" ]] ; then 113 | # Sparc is bi-endian but usually configured as big-endian. 114 | runtests "." 115 | runtests "hardfloat" 116 | runtests "32-bit" 117 | runtests "bigendian" 118 | runtest "--random 1000000" 119 | runtest "--random 1000000 --optimize" 120 | 121 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "mips" ]] ; then 122 | # MIPS is bi-endian but usually configured as big-endian. 123 | # XXX: should we run softfloat tests as well? Seems to depend on 124 | # the configuration... 125 | runtests "." 126 | runtests "hardfloat" 127 | runtests "32-bit" 128 | runtests "bigendian" 129 | runtest "--random 1000000" 130 | runtest "--random 1000000 --optimize" 131 | 132 | elif [[ $($LIRASM --show-arch 2>/dev/null) == "sh4" ]] ; then 133 | # SH4 is bi-endian but usually configured as big-endian. 134 | runtests "." 135 | runtests "hardfloat" 136 | runtests "32-bit" 137 | runtests "bigendian" 138 | runtest "--random 1000000" 139 | runtest "--random 1000000 --optimize" 140 | 141 | else 142 | echo "bad arch" 143 | exit 1 144 | fi 145 | 146 | rm testoutput.txt 147 | 148 | exit $exitcode 149 | -------------------------------------------------------------------------------- /lirasm/tests/32-bit/many_params.in: -------------------------------------------------------------------------------- 1 | .begin many_params 2 | pa = parami 0 0 3 | pb = parami 1 0 4 | pc = parami 2 0 5 | pd = parami 3 0 6 | pe = parami 4 0 7 | pf = parami 5 0 8 | pg = parami 6 0 9 | ph = parami 7 0 10 | res1 = addi pa pb 11 | res2 = addi res1 pc 12 | res3 = addi res2 pd 13 | res4 = addi res3 pe 14 | res5 = addi res4 pf 15 | res6 = addi res5 pg 16 | res7 = addi res6 ph 17 | reti res7 18 | .end 19 | 20 | .begin main 21 | a = immi 1 22 | b = immi 2 23 | c = immi 3 24 | d = immi 4 25 | e = immi 5 26 | f = immi 6 27 | g = immi 7 28 | h = immi 8 29 | res = calli many_params fastcall a b c d e f g h 30 | reti res 31 | .end 32 | -------------------------------------------------------------------------------- /lirasm/tests/32-bit/many_params.out: -------------------------------------------------------------------------------- 1 | Output is: 36 2 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/dasq.in: -------------------------------------------------------------------------------- 1 | q = immq 12345 2 | d = qasd q 3 | q2 = dasq d 4 | one = immd 1.0 ; do some intermediate stuff to make it less trivial 5 | two = immd 2.0 6 | three = addd one two 7 | i2 = q2i q2 8 | reti i2 9 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/dasq.out: -------------------------------------------------------------------------------- 1 | Output is: 12345 2 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/qasd.in: -------------------------------------------------------------------------------- 1 | one = immq 1 2 | d = immd 123.45 3 | q = dasq d 4 | q2 = addq q one ; do some intermediate stuff just to complicate things 5 | q3 = subq q2 one 6 | d2 = qasd q3 7 | retd d2 8 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/qasd.out: -------------------------------------------------------------------------------- 1 | Output is: 123.45 2 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/shq.in: -------------------------------------------------------------------------------- 1 | ; Only the bottom 6 bits of the shift amount in lshq/rshq/rshuq are used. 2 | 3 | two = immq 2 4 | 5 | sh1 = immi 1 6 | sh2 = immi 65 ; 0100_0001b 7 | sh3 = immi 268435393 ; 0000_1111_1111_1111_1111_1111_1100_0001b 8 | 9 | a1 = lshq two sh1 ; --> 4 10 | a2 = lshq two sh2 ; --> 4 11 | a3 = lshq two sh3 ; --> 4 12 | 13 | b1 = rshq two sh1 ; --> 1 14 | b2 = rshq two sh2 ; --> 1 15 | b3 = rshq two sh3 ; --> 1 16 | 17 | c1 = rshuq two sh1 ; --> 1 18 | c2 = rshuq two sh2 ; --> 1 19 | c3 = rshuq two sh3 ; --> 1 20 | 21 | s0 = immq 0 22 | s1 = addq s0 a1 23 | s2 = addq s1 a2 24 | s3 = addq s2 a3 25 | s4 = addq s3 b1 26 | s5 = addq s4 b2 27 | s6 = addq s5 b3 28 | s7 = addq s6 c1 29 | s8 = addq s7 c2 30 | s9 = addq s8 c2 ; --> 18 31 | 32 | retq s9 33 | -------------------------------------------------------------------------------- /lirasm/tests/64-bit/shq.out: -------------------------------------------------------------------------------- 1 | Output is: 18 2 | -------------------------------------------------------------------------------- /lirasm/tests/add.in: -------------------------------------------------------------------------------- 1 | two = immi 2 2 | three = immi 3 3 | res = addi two three 4 | reti res 5 | -------------------------------------------------------------------------------- /lirasm/tests/add.out: -------------------------------------------------------------------------------- 1 | Output is: 5 2 | -------------------------------------------------------------------------------- /lirasm/tests/addd.in: -------------------------------------------------------------------------------- 1 | ; Try to exercise as many different possibilities for the register allocator as 2 | ; is feasible. 3 | 4 | p1 = allocp 8 5 | p2 = allocp 8 6 | 7 | d1a = immd 1.5 8 | d1 = addd d1a d1a ; X = X + X 9 | std d1 p1 0 10 | 11 | d2a = immd 2.5 12 | d2b = immd 3.0 13 | d2 = addd d2a d2b ; X = X + Y 14 | std d2b p2 0 15 | std d2 p2 0 16 | 17 | d3a = ldd p1 0 18 | d3b = ldd p2 0 19 | d3 = addd d3a d3b ; X = Y + X 20 | std d3a p2 0 21 | std d3 p2 0 22 | 23 | d4a = ldd p2 0 24 | d4b = ldd p1 0 25 | d4 = addd d4a d4b ; X = Y + Z 26 | std d4a p1 0 27 | std d4b p2 0 28 | std d4 p1 0 29 | 30 | d = ldd p1 0 31 | retd d 32 | -------------------------------------------------------------------------------- /lirasm/tests/addd.out: -------------------------------------------------------------------------------- 1 | Output is: 11.5 2 | -------------------------------------------------------------------------------- /lirasm/tests/addjovi.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi 2147483647 4 | b = immi 0 5 | c = addjovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | -------------------------------------------------------------------------------- /lirasm/tests/addjovi.out: -------------------------------------------------------------------------------- 1 | Output is: 2147483647 2 | -------------------------------------------------------------------------------- /lirasm/tests/addjovi_ovf.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi 2147483647 4 | b = immi 1 5 | c = addjovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | -------------------------------------------------------------------------------- /lirasm/tests/addjovi_ovf.out: -------------------------------------------------------------------------------- 1 | Output is: 12345678 2 | -------------------------------------------------------------------------------- /lirasm/tests/addsub.in: -------------------------------------------------------------------------------- 1 | two = immi 7 2 | three = immi 3 3 | targ = addi two three 4 | res = subi targ three 5 | reti res 6 | -------------------------------------------------------------------------------- /lirasm/tests/addsub.out: -------------------------------------------------------------------------------- 1 | Output is: 7 2 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/fuzz-527178.in: -------------------------------------------------------------------------------- 1 | base = allocp 512 2 | five = immi 5 3 | sti five base 256 4 | x = ldus2ui base 258 5 | reti x 6 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/fuzz-527178.out: -------------------------------------------------------------------------------- 1 | Output is: 5 2 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/ldc2i.in: -------------------------------------------------------------------------------- 1 | full = immi 1288908529 ; 0x4cd32ef1 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi -15 ; sign_extend(0xf1) 6 | n1chk = immi 46 ; sign_extend(0x2e) 7 | n2chk = immi -45 ; sign_extend(0xd3) 8 | n3chk = immi 76 ; sign_extend(0x4c) 9 | 10 | n0 = ldc2i p 3 11 | n1 = ldc2i p 2 12 | n2 = ldc2i p 1 13 | n3 = ldc2i p 0 14 | 15 | ; Collate the results. 16 | r0 = xori n0chk n0 17 | r1 = xori n1chk n1 18 | r2 = xori n2chk n2 19 | r3 = xori n3chk n3 20 | 21 | r0_1 = ori r0 r1 22 | r2_3 = ori r2 r3 23 | 24 | r = ori r0_1 r2_3 25 | reti r 26 | 27 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/ldc2i.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/lds2i.in: -------------------------------------------------------------------------------- 1 | full = immi -249334698 ; 0xf1237456 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 29782 ; sign_extend(0x7456) 6 | n1chk = immi -3805 ; sign_extend(0xf123) 7 | 8 | n0 = lds2i p 2 9 | n1 = lds2i p 0 10 | 11 | ; Collate the results. 12 | r0 = xori n0chk n0 13 | r1 = xori n1chk n1 14 | 15 | r = ori r0 r1 16 | reti r 17 | 18 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/lds2i.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/lduc2ui.in: -------------------------------------------------------------------------------- 1 | full = immi -992746767 ; 0xc4d3e2f1 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 241 ; 0xf1 6 | n1chk = immi 226 ; 0xe2 7 | n2chk = immi 211 ; 0xd3 8 | n3chk = immi 196 ; 0xc4 9 | 10 | n0 = lduc2ui p 3 11 | n1 = lduc2ui p 2 12 | n2 = lduc2ui p 1 13 | n3 = lduc2ui p 0 14 | 15 | ; Collate the results. 16 | r0 = xori n0chk n0 17 | r1 = xori n1chk n1 18 | r2 = xori n2chk n2 19 | r3 = xori n3chk n3 20 | 21 | r0_1 = ori r0 r1 22 | r2_3 = ori r2 r3 23 | 24 | r = ori r0_1 r2_3 25 | reti r 26 | 27 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/lduc2ui.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/ldus2ui.in: -------------------------------------------------------------------------------- 1 | full = immi -249334698 ; 0xf1237456 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 29782 ; sign_extend(0x7456) 6 | n1chk = immi 61731 ; sign_extend(0xf123) 7 | 8 | n0 = ldus2ui p 2 9 | n1 = ldus2ui p 0 10 | 11 | ; Collate the results. 12 | r0 = xori n0chk n0 13 | r1 = xori n1chk n1 14 | 15 | r = ori r0 r1 16 | reti r 17 | 18 | -------------------------------------------------------------------------------- /lirasm/tests/bigendian/ldus2ui.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/bug596923.in: -------------------------------------------------------------------------------- 1 | ; Try to get asm_load64 (ldd) to store straight to a stack slot with a large 2 | ; offset from FP (on ARM, at least). 3 | 4 | a = immd 1.1 5 | p = allocp 1024 6 | std a p 0 7 | 8 | ; Emit the load just before a regfence, so the result does not have a register 9 | ; assigned. 10 | d = ldd p 0 11 | regfence 12 | 13 | retd d 14 | 15 | ; Ensure that 'p' is live here, so it gets a stack slot before 'd' does (and so 16 | ; extends the range required to store out 'd'). 17 | livep p 18 | -------------------------------------------------------------------------------- /lirasm/tests/bug596923.out: -------------------------------------------------------------------------------- 1 | Output is: 1.1 2 | -------------------------------------------------------------------------------- /lirasm/tests/call1.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | a = immi 65 3 | sti2c a ptr 0 4 | b = immi 66 5 | sti2c b ptr 1 6 | c = immi 67 7 | sti2c c ptr 2 8 | zero = immi 0 9 | sti2c zero ptr 3 10 | ss = calli puts cdecl ptr 11 | nn = gei ss zero 12 | reti nn 13 | -------------------------------------------------------------------------------- /lirasm/tests/call1.out: -------------------------------------------------------------------------------- 1 | ABC 2 | Output is: 1 3 | -------------------------------------------------------------------------------- /lirasm/tests/call2.in: -------------------------------------------------------------------------------- 1 | pi = immd 3.14 2 | half = immd 0.5 3 | halfpi = muld pi half 4 | res = calld sin cdecl halfpi 5 | retd res 6 | -------------------------------------------------------------------------------- /lirasm/tests/call2.out: -------------------------------------------------------------------------------- 1 | Output is: 1 2 | -------------------------------------------------------------------------------- /lirasm/tests/calld1.in: -------------------------------------------------------------------------------- 1 | a = immd 1.1; 2 | b = immd 2.2 3 | c = immd 3.3; 4 | d = immd 4.4; 5 | e = immd 5.5; 6 | f = immd 6.6; 7 | g = immd 7.7; 8 | h = immd 8.8; 9 | 10 | res = calld calld1 cdecl a b c d e f g h 11 | retd res 12 | -------------------------------------------------------------------------------- /lirasm/tests/calld1.out: -------------------------------------------------------------------------------- 1 | Output is: -62.9667 2 | -------------------------------------------------------------------------------- /lirasm/tests/callid1.in: -------------------------------------------------------------------------------- 1 | i = immi -1; 2 | j = immi 3; 3 | k = immi 6; 4 | x = immd 1.1; 5 | y = immd 3.3; 6 | z = immd 4.4; 7 | 8 | res = calld callid1 cdecl i x y j k z 9 | retd res 10 | 11 | -------------------------------------------------------------------------------- /lirasm/tests/callid1.out: -------------------------------------------------------------------------------- 1 | Output is: 1.1 2 | -------------------------------------------------------------------------------- /lirasm/tests/callid2.in: -------------------------------------------------------------------------------- 1 | i = immi -1; 2 | j = immi 3; 3 | k = immi 6; 4 | x = immd 8.8; 5 | 6 | res = calld callid2 cdecl i j k x 7 | retd res 8 | 9 | -------------------------------------------------------------------------------- /lirasm/tests/callid2.out: -------------------------------------------------------------------------------- 1 | Output is: 1.1 2 | -------------------------------------------------------------------------------- /lirasm/tests/callid3.in: -------------------------------------------------------------------------------- 1 | i = immi -1; 2 | j = immi 3; 3 | k = immi 6; 4 | x = immd 1.1; 5 | y = immd 3.3; 6 | z = immd 4.4; 7 | 8 | res = calld callid3 cdecl i j x k y z 9 | retd res 10 | 11 | -------------------------------------------------------------------------------- /lirasm/tests/callid3.out: -------------------------------------------------------------------------------- 1 | Output is: 1.1 2 | -------------------------------------------------------------------------------- /lirasm/tests/callv.in: -------------------------------------------------------------------------------- 1 | ; test call to void function 2 | 3 | forty_two = immi 42 4 | callv printi cdecl forty_two 5 | reti forty_two 6 | -------------------------------------------------------------------------------- /lirasm/tests/callv.out: -------------------------------------------------------------------------------- 1 | 42 2 | Output is: 42 3 | -------------------------------------------------------------------------------- /lirasm/tests/cmov.in: -------------------------------------------------------------------------------- 1 | i = immi -1 2 | j = immi 0 3 | k = immi 1 4 | 5 | ; Test each comparison operator. In each case, the result is set to k (1) if it 6 | ; did what it should do, or i (-1) if not. 7 | 8 | c1 = eqi j k 9 | r1 = cmovi c1 i k 10 | 11 | c2 = lti j k 12 | r2 = cmovi c2 k i 13 | 14 | c3 = lei j k 15 | r3 = cmovi c3 k i 16 | 17 | c4 = gti j k 18 | r4 = cmovi c4 i k 19 | 20 | c5 = gei j k 21 | r5 = cmovi c5 i k 22 | 23 | c6 = ltui j k 24 | r6 = cmovi c6 k i 25 | 26 | c7 = leui j k 27 | r7 = cmovi c7 k i 28 | 29 | c8 = gtui j k 30 | r8 = cmovi c8 i k 31 | 32 | c9 = geui j k 33 | r9 = cmovi c9 i k 34 | 35 | ; A few weird cases: Perform unsigned tests on a signed quantity to ensure that 36 | ; they do what they should. This is dependent on the platform using two's 37 | ; complement arithmetic, but we don't support anything that doesn't do that. 38 | 39 | c10 = ltui i k 40 | r10 = cmovi c10 i k 41 | 42 | c11 = leui i k 43 | r11 = cmovi c11 i k 44 | 45 | c12 = gtui i k 46 | r12 = cmovi c12 k i 47 | 48 | c13 = geui i k 49 | r13 = cmovi c13 k i 50 | 51 | ; Sum the results. They should all be 1 so an overall result of 13 is a pass. 52 | 53 | r1_2 = addi r1 r2 54 | r3_4 = addi r3 r4 55 | r5_6 = addi r5 r6 56 | r7_8 = addi r7 r8 57 | r9_10 = addi r9 r10 58 | r11_12 = addi r11 r12 59 | 60 | r1_4 = addi r1_2 r3_4 61 | r5_8 = addi r5_6 r7_8 62 | r9_12 = addi r9_10 r11_12 63 | 64 | r1_8 = addi r1_4 r5_8 65 | r9_13 = addi r9_12 r13 66 | 67 | res = addi r1_8 r9_13 68 | reti res 69 | -------------------------------------------------------------------------------- /lirasm/tests/cmov.out: -------------------------------------------------------------------------------- 1 | Output is: 13 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_eqd.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants. 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immd 0 13 | i1 = immd 1 14 | i2 = immd -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'eqd'. 18 | eq0 = eqd i0 i0 ; 1 19 | eq1 = eqd i0 i1 ; 0 20 | eq2 = eqd i0 i2 ; 0 21 | eq3 = eqd i1 i0 ; 0 22 | eq4 = eqd i1 i1 ; 1 23 | eq5 = eqd i1 i2 ; 0 24 | eq6 = eqd i2 i0 ; 0 25 | eq7 = eqd i2 i1 ; 0 26 | eq8 = eqd i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | eq0sh = lshi eq0 sh0 30 | eq1sh = lshi eq1 sh1 31 | eq2sh = lshi eq2 sh2 32 | eq3sh = lshi eq3 sh3 33 | eq4sh = lshi eq4 sh4 34 | eq5sh = lshi eq5 sh5 35 | eq6sh = lshi eq6 sh6 36 | eq7sh = lshi eq7 sh7 37 | eq8sh = lshi eq8 sh8 38 | 39 | eq0_1 = ori eq0sh eq1sh 40 | eq2_3 = ori eq2sh eq3sh 41 | eq4_5 = ori eq4sh eq5sh 42 | eq6_7 = ori eq6sh eq7sh 43 | 44 | eq0_3 = ori eq0_1 eq2_3 45 | eq4_7 = ori eq4_5 eq6_7 46 | 47 | eq0_7 = ori eq0_3 eq4_7 48 | 49 | eq = ori eq0_7 eq8sh 50 | 51 | ; The result should be {0001,0001,0001}, 0x111, or 273. 52 | 53 | reti eq 54 | 55 | -------------------------------------------------------------------------------- /lirasm/tests/cond_eqd.out: -------------------------------------------------------------------------------- 1 | Output is: 273 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_eqi.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'eqi'. 18 | eq0 = eqi i0 i0 ; 1 19 | eq1 = eqi i0 i1 ; 0 20 | eq2 = eqi i0 i2 ; 0 21 | eq3 = eqi i1 i0 ; 0 22 | eq4 = eqi i1 i1 ; 1 23 | eq5 = eqi i1 i2 ; 0 24 | eq6 = eqi i2 i0 ; 0 25 | eq7 = eqi i2 i1 ; 0 26 | eq8 = eqi i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | eq0sh = lshi eq0 sh0 30 | eq1sh = lshi eq1 sh1 31 | eq2sh = lshi eq2 sh2 32 | eq3sh = lshi eq3 sh3 33 | eq4sh = lshi eq4 sh4 34 | eq5sh = lshi eq5 sh5 35 | eq6sh = lshi eq6 sh6 36 | eq7sh = lshi eq7 sh7 37 | eq8sh = lshi eq8 sh8 38 | 39 | eq0_1 = ori eq0sh eq1sh 40 | eq2_3 = ori eq2sh eq3sh 41 | eq4_5 = ori eq4sh eq5sh 42 | eq6_7 = ori eq6sh eq7sh 43 | 44 | eq0_3 = ori eq0_1 eq2_3 45 | eq4_7 = ori eq4_5 eq6_7 46 | 47 | eq0_7 = ori eq0_3 eq4_7 48 | 49 | eq = ori eq0_7 eq8sh 50 | 51 | ; The result should be {0001,0001,0001}, 0x111, or 273. 52 | 53 | reti eq 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_eqi.out: -------------------------------------------------------------------------------- 1 | Output is: 273 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ged.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immd 0 13 | i1 = immd 1 14 | i2 = immd -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'ged'. 18 | ge0 = ged i0 i0 ; 1 19 | ge1 = ged i0 i1 ; 0 20 | ge2 = ged i0 i2 ; 1 21 | ge3 = ged i1 i0 ; 1 22 | ge4 = ged i1 i1 ; 1 23 | ge5 = ged i1 i2 ; 1 24 | ge6 = ged i2 i0 ; 0 25 | ge7 = ged i2 i1 ; 0 26 | ge8 = ged i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | ge0sh = lshi ge0 sh0 30 | ge1sh = lshi ge1 sh1 31 | ge2sh = lshi ge2 sh2 32 | ge3sh = lshi ge3 sh3 33 | ge4sh = lshi ge4 sh4 34 | ge5sh = lshi ge5 sh5 35 | ge6sh = lshi ge6 sh6 36 | ge7sh = lshi ge7 sh7 37 | ge8sh = lshi ge8 sh8 38 | 39 | ge0_1 = ori ge0sh ge1sh 40 | ge2_3 = ori ge2sh ge3sh 41 | ge4_5 = ori ge4sh ge5sh 42 | ge6_7 = ori ge6sh ge7sh 43 | 44 | ge0_3 = ori ge0_1 ge2_3 45 | ge4_7 = ori ge4_5 ge6_7 46 | 47 | ge0_7 = ori ge0_3 ge4_7 48 | 49 | ge = ori ge0_7 ge8sh 50 | 51 | ; The result should be {0001,0011,1101}, 0x13d, or 44. 52 | 53 | reti ge 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ged.out: -------------------------------------------------------------------------------- 1 | Output is: 317 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gei.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'gei'. 18 | ge0 = gei i0 i0 ; 1 19 | ge1 = gei i0 i1 ; 0 20 | ge2 = gei i0 i2 ; 1 21 | ge3 = gei i1 i0 ; 1 22 | ge4 = gei i1 i1 ; 1 23 | ge5 = gei i1 i2 ; 1 24 | ge6 = gei i2 i0 ; 0 25 | ge7 = gei i2 i1 ; 0 26 | ge8 = gei i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | ge0sh = lshi ge0 sh0 30 | ge1sh = lshi ge1 sh1 31 | ge2sh = lshi ge2 sh2 32 | ge3sh = lshi ge3 sh3 33 | ge4sh = lshi ge4 sh4 34 | ge5sh = lshi ge5 sh5 35 | ge6sh = lshi ge6 sh6 36 | ge7sh = lshi ge7 sh7 37 | ge8sh = lshi ge8 sh8 38 | 39 | ge0_1 = ori ge0sh ge1sh 40 | ge2_3 = ori ge2sh ge3sh 41 | ge4_5 = ori ge4sh ge5sh 42 | ge6_7 = ori ge6sh ge7sh 43 | 44 | ge0_3 = ori ge0_1 ge2_3 45 | ge4_7 = ori ge4_5 ge6_7 46 | 47 | ge0_7 = ori ge0_3 ge4_7 48 | 49 | ge = ori ge0_7 ge8sh 50 | 51 | ; The result should be {0001,0011,1101}, 0x13d, or 44. 52 | 53 | reti ge 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gei.out: -------------------------------------------------------------------------------- 1 | Output is: 317 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_geui.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'geui'. 18 | ge0 = geui i0 i0 ; 1 19 | ge1 = geui i0 i1 ; 0 20 | ge2 = geui i0 i2 ; 0 21 | ge3 = geui i1 i0 ; 1 22 | ge4 = geui i1 i1 ; 1 23 | ge5 = geui i1 i2 ; 0 24 | ge6 = geui i2 i0 ; 1 25 | ge7 = geui i2 i1 ; 1 26 | ge8 = geui i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | ge0sh = lshi ge0 sh0 30 | ge1sh = lshi ge1 sh1 31 | ge2sh = lshi ge2 sh2 32 | ge3sh = lshi ge3 sh3 33 | ge4sh = lshi ge4 sh4 34 | ge5sh = lshi ge5 sh5 35 | ge6sh = lshi ge6 sh6 36 | ge7sh = lshi ge7 sh7 37 | ge8sh = lshi ge8 sh8 38 | 39 | ge0_1 = ori ge0sh ge1sh 40 | ge2_3 = ori ge2sh ge3sh 41 | ge4_5 = ori ge4sh ge5sh 42 | ge6_7 = ori ge6sh ge7sh 43 | 44 | ge0_3 = ori ge0_1 ge2_3 45 | ge4_7 = ori ge4_5 ge6_7 46 | 47 | ge0_7 = ori ge0_3 ge4_7 48 | 49 | ge = ori ge0_7 ge8sh 50 | 51 | ; The result should be {0001,1101,1001}, 0x1d9, or 473. 52 | 53 | reti ge 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_geui.out: -------------------------------------------------------------------------------- 1 | Output is: 473 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gtd.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immd 0 13 | i1 = immd 1 14 | i2 = immd -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'gtd'. 18 | gt0 = gtd i0 i0 ; 0 19 | gt1 = gtd i0 i1 ; 0 20 | gt2 = gtd i0 i2 ; 1 21 | gt3 = gtd i1 i0 ; 1 22 | gt4 = gtd i1 i1 ; 0 23 | gt5 = gtd i1 i2 ; 1 24 | gt6 = gtd i2 i0 ; 0 25 | gt7 = gtd i2 i1 ; 0 26 | gt8 = gtd i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | gt0sh = lshi gt0 sh0 30 | gt1sh = lshi gt1 sh1 31 | gt2sh = lshi gt2 sh2 32 | gt3sh = lshi gt3 sh3 33 | gt4sh = lshi gt4 sh4 34 | gt5sh = lshi gt5 sh5 35 | gt6sh = lshi gt6 sh6 36 | gt7sh = lshi gt7 sh7 37 | gt8sh = lshi gt8 sh8 38 | 39 | gt0_1 = ori gt0sh gt1sh 40 | gt2_3 = ori gt2sh gt3sh 41 | gt4_5 = ori gt4sh gt5sh 42 | gt6_7 = ori gt6sh gt7sh 43 | 44 | gt0_3 = ori gt0_1 gt2_3 45 | gt4_7 = ori gt4_5 gt6_7 46 | 47 | gt0_7 = ori gt0_3 gt4_7 48 | 49 | gt = ori gt0_7 gt8sh 50 | 51 | ; The result should be {0000,0010,1100}, 0x02c, or 194. 52 | 53 | reti gt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gtd.out: -------------------------------------------------------------------------------- 1 | Output is: 44 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gti.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'gti'. 18 | gt0 = gti i0 i0 ; 0 19 | gt1 = gti i0 i1 ; 0 20 | gt2 = gti i0 i2 ; 1 21 | gt3 = gti i1 i0 ; 1 22 | gt4 = gti i1 i1 ; 0 23 | gt5 = gti i1 i2 ; 1 24 | gt6 = gti i2 i0 ; 0 25 | gt7 = gti i2 i1 ; 0 26 | gt8 = gti i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | gt0sh = lshi gt0 sh0 30 | gt1sh = lshi gt1 sh1 31 | gt2sh = lshi gt2 sh2 32 | gt3sh = lshi gt3 sh3 33 | gt4sh = lshi gt4 sh4 34 | gt5sh = lshi gt5 sh5 35 | gt6sh = lshi gt6 sh6 36 | gt7sh = lshi gt7 sh7 37 | gt8sh = lshi gt8 sh8 38 | 39 | gt0_1 = ori gt0sh gt1sh 40 | gt2_3 = ori gt2sh gt3sh 41 | gt4_5 = ori gt4sh gt5sh 42 | gt6_7 = ori gt6sh gt7sh 43 | 44 | gt0_3 = ori gt0_1 gt2_3 45 | gt4_7 = ori gt4_5 gt6_7 46 | 47 | gt0_7 = ori gt0_3 gt4_7 48 | 49 | gt = ori gt0_7 gt8sh 50 | 51 | ; The result should be {0000,0010,1100}, 0x02c, or 194. 52 | 53 | reti gt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gti.out: -------------------------------------------------------------------------------- 1 | Output is: 44 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gtui.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants. 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'gtui'. 18 | gt0 = gtui i0 i0 ; 0 19 | gt1 = gtui i0 i1 ; 0 20 | gt2 = gtui i0 i2 ; 0 21 | gt3 = gtui i1 i0 ; 1 22 | gt4 = gtui i1 i1 ; 0 23 | gt5 = gtui i1 i2 ; 0 24 | gt6 = gtui i2 i0 ; 1 25 | gt7 = gtui i2 i1 ; 1 26 | gt8 = gtui i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | gt0sh = lshi gt0 sh0 30 | gt1sh = lshi gt1 sh1 31 | gt2sh = lshi gt2 sh2 32 | gt3sh = lshi gt3 sh3 33 | gt4sh = lshi gt4 sh4 34 | gt5sh = lshi gt5 sh5 35 | gt6sh = lshi gt6 sh6 36 | gt7sh = lshi gt7 sh7 37 | gt8sh = lshi gt8 sh8 38 | 39 | gt0_1 = ori gt0sh gt1sh 40 | gt2_3 = ori gt2sh gt3sh 41 | gt4_5 = ori gt4sh gt5sh 42 | gt6_7 = ori gt6sh gt7sh 43 | 44 | gt0_3 = ori gt0_1 gt2_3 45 | gt4_7 = ori gt4_5 gt6_7 46 | 47 | gt0_7 = ori gt0_3 gt4_7 48 | 49 | gt = ori gt0_7 gt8sh 50 | 51 | ; The result should be {0000,1100,1000}, 0x0c8, or 200. 52 | 53 | reti gt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_gtui.out: -------------------------------------------------------------------------------- 1 | Output is: 200 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_led.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immd 0 13 | i1 = immd 1 14 | i2 = immd -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'led'. 18 | le0 = led i0 i0 ; 1 19 | le1 = led i0 i1 ; 1 20 | le2 = led i0 i2 ; 0 21 | le3 = led i1 i0 ; 0 22 | le4 = led i1 i1 ; 1 23 | le5 = led i1 i2 ; 0 24 | le6 = led i2 i0 ; 1 25 | le7 = led i2 i1 ; 1 26 | le8 = led i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | le0sh = lshi le0 sh0 30 | le1sh = lshi le1 sh1 31 | le2sh = lshi le2 sh2 32 | le3sh = lshi le3 sh3 33 | le4sh = lshi le4 sh4 34 | le5sh = lshi le5 sh5 35 | le6sh = lshi le6 sh6 36 | le7sh = lshi le7 sh7 37 | le8sh = lshi le8 sh8 38 | 39 | le0_1 = ori le0sh le1sh 40 | le2_3 = ori le2sh le3sh 41 | le4_5 = ori le4sh le5sh 42 | le6_7 = ori le6sh le7sh 43 | 44 | le0_3 = ori le0_1 le2_3 45 | le4_7 = ori le4_5 le6_7 46 | 47 | le0_7 = ori le0_3 le4_7 48 | 49 | le = ori le0_7 le8sh 50 | 51 | ; The result should be {0001,1101,0011}, 0x1d3, or 194. 52 | 53 | reti le 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_led.out: -------------------------------------------------------------------------------- 1 | Output is: 467 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_lei.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'lei'. 18 | le0 = lei i0 i0 ; 1 19 | le1 = lei i0 i1 ; 1 20 | le2 = lei i0 i2 ; 0 21 | le3 = lei i1 i0 ; 0 22 | le4 = lei i1 i1 ; 1 23 | le5 = lei i1 i2 ; 0 24 | le6 = lei i2 i0 ; 1 25 | le7 = lei i2 i1 ; 1 26 | le8 = lei i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | le0sh = lshi le0 sh0 30 | le1sh = lshi le1 sh1 31 | le2sh = lshi le2 sh2 32 | le3sh = lshi le3 sh3 33 | le4sh = lshi le4 sh4 34 | le5sh = lshi le5 sh5 35 | le6sh = lshi le6 sh6 36 | le7sh = lshi le7 sh7 37 | le8sh = lshi le8 sh8 38 | 39 | le0_1 = ori le0sh le1sh 40 | le2_3 = ori le2sh le3sh 41 | le4_5 = ori le4sh le5sh 42 | le6_7 = ori le6sh le7sh 43 | 44 | le0_3 = ori le0_1 le2_3 45 | le4_7 = ori le4_5 le6_7 46 | 47 | le0_7 = ori le0_3 le4_7 48 | 49 | le = ori le0_7 le8sh 50 | 51 | ; The result should be {0001,1101,0011}, 0x1d3, or 194. 52 | 53 | reti le 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_lei.out: -------------------------------------------------------------------------------- 1 | Output is: 467 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_leui.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'leui'. 18 | le0 = leui i0 i0 ; 1 19 | le1 = leui i0 i1 ; 1 20 | le2 = leui i0 i2 ; 1 21 | le3 = leui i1 i0 ; 0 22 | le4 = leui i1 i1 ; 1 23 | le5 = leui i1 i2 ; 1 24 | le6 = leui i2 i0 ; 0 25 | le7 = leui i2 i1 ; 0 26 | le8 = leui i2 i2 ; 1 27 | 28 | ; Aggregate the results. 29 | le0sh = lshi le0 sh0 30 | le1sh = lshi le1 sh1 31 | le2sh = lshi le2 sh2 32 | le3sh = lshi le3 sh3 33 | le4sh = lshi le4 sh4 34 | le5sh = lshi le5 sh5 35 | le6sh = lshi le6 sh6 36 | le7sh = lshi le7 sh7 37 | le8sh = lshi le8 sh8 38 | 39 | le0_1 = ori le0sh le1sh 40 | le2_3 = ori le2sh le3sh 41 | le4_5 = ori le4sh le5sh 42 | le6_7 = ori le6sh le7sh 43 | 44 | le0_3 = ori le0_1 le2_3 45 | le4_7 = ori le4_5 le6_7 46 | 47 | le0_7 = ori le0_3 le4_7 48 | 49 | le = ori le0_7 le8sh 50 | 51 | ; The result should be {0001,0011,0111}, 0x137, or 311. 52 | 53 | reti le 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_leui.out: -------------------------------------------------------------------------------- 1 | Output is: 311 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ltd.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immd 0 13 | i1 = immd 1 14 | i2 = immd -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'ltd'. 18 | lt0 = ltd i0 i0 ; 0 19 | lt1 = ltd i0 i1 ; 1 20 | lt2 = ltd i0 i2 ; 0 21 | lt3 = ltd i1 i0 ; 0 22 | lt4 = ltd i1 i1 ; 0 23 | lt5 = ltd i1 i2 ; 0 24 | lt6 = ltd i2 i0 ; 1 25 | lt7 = ltd i2 i1 ; 1 26 | lt8 = ltd i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | lt0sh = lshi lt0 sh0 30 | lt1sh = lshi lt1 sh1 31 | lt2sh = lshi lt2 sh2 32 | lt3sh = lshi lt3 sh3 33 | lt4sh = lshi lt4 sh4 34 | lt5sh = lshi lt5 sh5 35 | lt6sh = lshi lt6 sh6 36 | lt7sh = lshi lt7 sh7 37 | lt8sh = lshi lt8 sh8 38 | 39 | lt0_1 = ori lt0sh lt1sh 40 | lt2_3 = ori lt2sh lt3sh 41 | lt4_5 = ori lt4sh lt5sh 42 | lt6_7 = ori lt6sh lt7sh 43 | 44 | lt0_3 = ori lt0_1 lt2_3 45 | lt4_7 = ori lt4_5 lt6_7 46 | 47 | lt0_7 = ori lt0_3 lt4_7 48 | 49 | lt = ori lt0_7 lt8sh 50 | 51 | ; The result should be {0000,1100,0010}, 0x0c2, or 194. 52 | 53 | reti lt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ltd.out: -------------------------------------------------------------------------------- 1 | Output is: 194 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_lti.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'lti'. 18 | lt0 = lti i0 i0 ; 0 19 | lt1 = lti i0 i1 ; 1 20 | lt2 = lti i0 i2 ; 0 21 | lt3 = lti i1 i0 ; 0 22 | lt4 = lti i1 i1 ; 0 23 | lt5 = lti i1 i2 ; 0 24 | lt6 = lti i2 i0 ; 1 25 | lt7 = lti i2 i1 ; 1 26 | lt8 = lti i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | lt0sh = lshi lt0 sh0 30 | lt1sh = lshi lt1 sh1 31 | lt2sh = lshi lt2 sh2 32 | lt3sh = lshi lt3 sh3 33 | lt4sh = lshi lt4 sh4 34 | lt5sh = lshi lt5 sh5 35 | lt6sh = lshi lt6 sh6 36 | lt7sh = lshi lt7 sh7 37 | lt8sh = lshi lt8 sh8 38 | 39 | lt0_1 = ori lt0sh lt1sh 40 | lt2_3 = ori lt2sh lt3sh 41 | lt4_5 = ori lt4sh lt5sh 42 | lt6_7 = ori lt6sh lt7sh 43 | 44 | lt0_3 = ori lt0_1 lt2_3 45 | lt4_7 = ori lt4_5 lt6_7 46 | 47 | lt0_7 = ori lt0_3 lt4_7 48 | 49 | lt = ori lt0_7 lt8sh 50 | 51 | ; The result should be {0000,1100,0010}, 0x0c2, or 194. 52 | 53 | reti lt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_lti.out: -------------------------------------------------------------------------------- 1 | Output is: 194 2 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ltui.in: -------------------------------------------------------------------------------- 1 | ; A few utility constants . 2 | sh0 = immi 0 3 | sh1 = immi 1 4 | sh2 = immi 2 5 | sh3 = immi 3 6 | sh4 = immi 4 7 | sh5 = immi 5 8 | sh6 = immi 6 9 | sh7 = immi 7 10 | sh8 = immi 8 11 | 12 | i0 = immi 0 13 | i1 = immi 1 14 | i2 = immi -1 15 | 16 | ; ---------------------------------------------------------------------------- 17 | ; Combinations of 'ltui'. 18 | lt0 = ltui i0 i0 ; 0 19 | lt1 = ltui i0 i1 ; 1 20 | lt2 = ltui i0 i2 ; 1 21 | lt3 = ltui i1 i0 ; 0 22 | lt4 = ltui i1 i1 ; 0 23 | lt5 = ltui i1 i2 ; 1 24 | lt6 = ltui i2 i0 ; 0 25 | lt7 = ltui i2 i1 ; 0 26 | lt8 = ltui i2 i2 ; 0 27 | 28 | ; Aggregate the results. 29 | lt0sh = lshi lt0 sh0 30 | lt1sh = lshi lt1 sh1 31 | lt2sh = lshi lt2 sh2 32 | lt3sh = lshi lt3 sh3 33 | lt4sh = lshi lt4 sh4 34 | lt5sh = lshi lt5 sh5 35 | lt6sh = lshi lt6 sh6 36 | lt7sh = lshi lt7 sh7 37 | lt8sh = lshi lt8 sh8 38 | 39 | lt0_1 = ori lt0sh lt1sh 40 | lt2_3 = ori lt2sh lt3sh 41 | lt4_5 = ori lt4sh lt5sh 42 | lt6_7 = ori lt6sh lt7sh 43 | 44 | lt0_3 = ori lt0_1 lt2_3 45 | lt4_7 = ori lt4_5 lt6_7 46 | 47 | lt0_7 = ori lt0_3 lt4_7 48 | 49 | lt = ori lt0_7 lt8sh 50 | 51 | ; The result should be {0000,0010,0110}, 0x026, or 38. 52 | 53 | reti lt 54 | -------------------------------------------------------------------------------- /lirasm/tests/cond_ltui.out: -------------------------------------------------------------------------------- 1 | Output is: 38 2 | -------------------------------------------------------------------------------- /lirasm/tests/divd.in: -------------------------------------------------------------------------------- 1 | ; Try to exercise as many different possibilities for the register allocator as 2 | ; is feasible. 3 | 4 | p1 = allocp 8 5 | p2 = allocp 8 6 | 7 | d1a = immd 1.5 8 | d1 = divd d1a d1a ; X = X / X 9 | std d1 p1 0 10 | 11 | d2a = immd 4.0 12 | d2b = immd 8.0 13 | d2 = divd d2a d2b ; X = X / Y 14 | std d2b p2 0 15 | std d2 p2 0 16 | 17 | d3a = ldd p1 0 18 | d3b = ldd p2 0 19 | d3 = divd d3a d3b ; X = Y / X 20 | std d3a p2 0 21 | std d3 p2 0 22 | 23 | d4a = ldd p2 0 24 | d4b = ldd p1 0 25 | d4 = divd d4a d4b ; X = Y / Z 26 | std d4a p1 0 27 | std d4b p2 0 28 | std d4 p1 0 29 | 30 | d = ldd p1 0 31 | retd d 32 | -------------------------------------------------------------------------------- /lirasm/tests/divd.out: -------------------------------------------------------------------------------- 1 | Output is: 2 2 | -------------------------------------------------------------------------------- /lirasm/tests/float_double.in: -------------------------------------------------------------------------------- 1 | doubleA = immd 1.25 ; single precision 2 | doubleB = immd 4.5 ; single precision 3 | doubleC = immd 1.2 ; not single precision 4 | 5 | ptr = allocp 12 6 | std2f doubleA ptr 0 7 | std2f doubleB ptr 4 8 | std2f doubleC ptr 8 9 | 10 | doubleD = ldf2d ptr 0 11 | doubleE = ldf2d ptr 4 12 | doubleF = ldf2d ptr 8 13 | 14 | resA = eqd doubleA doubleD ; true 15 | resB = eqd doubleB doubleE ; true 16 | resC = eqd doubleB doubleF ; false 17 | resD = addi resA resB 18 | resE = addi resC resD 19 | 20 | reti resE 21 | -------------------------------------------------------------------------------- /lirasm/tests/float_double.out: -------------------------------------------------------------------------------- 1 | Output is: 2 2 | -------------------------------------------------------------------------------- /lirasm/tests/floatingpoint.in: -------------------------------------------------------------------------------- 1 | pi = immd 3.14 2 | two = immd 2.0 3 | TwoPi = muld pi two 4 | retd two 5 | -------------------------------------------------------------------------------- /lirasm/tests/floatingpoint.out: -------------------------------------------------------------------------------- 1 | Output is: 2 2 | -------------------------------------------------------------------------------- /lirasm/tests/fneg.in: -------------------------------------------------------------------------------- 1 | p = immd 123.456 2 | n = negd p 3 | retd n 4 | -------------------------------------------------------------------------------- /lirasm/tests/fneg.out: -------------------------------------------------------------------------------- 1 | Output is: -123.456 2 | -------------------------------------------------------------------------------- /lirasm/tests/fpu1-598151.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immd 1.0 4 | b = immd 2.5 5 | c = addd a b 6 | std c ptr 0 7 | j done 8 | 9 | foo: std c ptr 0 10 | 11 | done: res = ldd ptr 0 12 | retd res 13 | -------------------------------------------------------------------------------- /lirasm/tests/fpu1-598151.out: -------------------------------------------------------------------------------- 1 | Output is: 3.5 2 | -------------------------------------------------------------------------------- /lirasm/tests/fpu2-598151.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | k = immd 1.0 4 | std k ptr 0 5 | 6 | a = immd 1.0 7 | b = immd 2.5 8 | c = addd a b 9 | std c ptr 0 10 | 11 | x = ldd ptr 0 12 | z = immd 0.0 13 | p = eqd x z 14 | jt p skip 15 | 16 | j done 17 | 18 | skip: std c ptr 0 19 | 20 | done: res = ldd ptr 0 21 | retd res 22 | -------------------------------------------------------------------------------- /lirasm/tests/fpu2-598151.out: -------------------------------------------------------------------------------- 1 | Output is: 3.5 2 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/d2i.in: -------------------------------------------------------------------------------- 1 | ; The rounding rules for d2i are pretty relaxed, but integer values should 2 | ; convert cleanly. 3 | c1 = immi -2147483648 4 | d1 = immd -2147483648 5 | i1 = d2i d1 6 | r1 = xori c1 i1 7 | 8 | c2 = immi 2147483647 9 | d2 = immd 2147483647 10 | i2 = d2i d2 11 | r2 = xori i2 c2 12 | 13 | ; The ARM back-end will do something different if there is no machine register 14 | ; allocated for d2i, and it doesn't hurt to test the same thing on other 15 | ; platforms too: 16 | 17 | c3 = immi 123456 18 | d3 = immd 123456 19 | i3 = d2i d3 20 | regfence 21 | r3 = xori i3 c3 22 | 23 | res1_2 = ori r1 r2 24 | res1_3 = ori res1_2 r3 25 | 26 | reti res1_3 27 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/d2i.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/f2i.in: -------------------------------------------------------------------------------- 1 | a = allocp 8 2 | d = immd 5.0 3 | std d a 0 4 | x = ldd a 0 5 | i = d2i x 6 | reti i 7 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/f2i.out: -------------------------------------------------------------------------------- 1 | Output is: 5 2 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/i2d.in: -------------------------------------------------------------------------------- 1 | ; This test assumes that d2i and 32-bit integer arithmetic works properly. 2 | 3 | ; Start with 0x80000000 4 | i1 = immi -2147483648 5 | d1 = i2d i1 6 | o1 = d2i d1 7 | 8 | ; Test with -1 9 | c2 = immi 2147483647 10 | i2 = addi o1 c2 11 | d2 = i2d i2 12 | o2 = d2i d2 13 | 14 | ; Test with 2147483647 15 | i3 = subi o2 i1 16 | d3 = i2d i3 17 | o3 = d2i d3 18 | 19 | ; Test with 0 20 | i4 = subi o3 c2 21 | d4 = i2d i4 22 | o4 = d2i d4 23 | 24 | reti o4 25 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/i2d.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/ui2d.in: -------------------------------------------------------------------------------- 1 | i = immi -1 2 | d = ui2d i 3 | 4 | retd d 5 | 6 | -------------------------------------------------------------------------------- /lirasm/tests/hardfloat/ui2d.out: -------------------------------------------------------------------------------- 1 | Output is: 4.29497e+09 2 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/fuzz-527178.in: -------------------------------------------------------------------------------- 1 | base = allocp 512 2 | five = immi 5 3 | sti five base 256 4 | x = ldus2ui base 256 5 | reti x 6 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/fuzz-527178.out: -------------------------------------------------------------------------------- 1 | Output is: 5 2 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/ldc2i.in: -------------------------------------------------------------------------------- 1 | full = immi 1288908529 ; 0x4cd32ef1 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi -15 ; sign_extend(0xf1) 6 | n1chk = immi 46 ; sign_extend(0x2e) 7 | n2chk = immi -45 ; sign_extend(0xd3) 8 | n3chk = immi 76 ; sign_extend(0x4c) 9 | 10 | n0 = ldc2i p 0 11 | n1 = ldc2i p 1 12 | n2 = ldc2i p 2 13 | n3 = ldc2i p 3 14 | 15 | ; Collate the results. 16 | r0 = xori n0chk n0 17 | r1 = xori n1chk n1 18 | r2 = xori n2chk n2 19 | r3 = xori n3chk n3 20 | 21 | r0_1 = ori r0 r1 22 | r2_3 = ori r2 r3 23 | 24 | r = ori r0_1 r2_3 25 | reti r 26 | 27 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/ldc2i.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/lds2i.in: -------------------------------------------------------------------------------- 1 | full = immi -249334698 ; 0xf1237456 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 29782 ; sign_extend(0x7456) 6 | n1chk = immi -3805 ; sign_extend(0xf123) 7 | 8 | n0 = lds2i p 0 9 | n1 = lds2i p 2 10 | 11 | ; Collate the results. 12 | r0 = xori n0chk n0 13 | r1 = xori n1chk n1 14 | 15 | r = ori r0 r1 16 | reti r 17 | 18 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/lds2i.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/lduc2ui.in: -------------------------------------------------------------------------------- 1 | full = immi -992746767 ; 0xc4d3e2f1 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 241 ; 0xf1 6 | n1chk = immi 226 ; 0xe2 7 | n2chk = immi 211 ; 0xd3 8 | n3chk = immi 196 ; 0xc4 9 | 10 | n0 = lduc2ui p 0 11 | n1 = lduc2ui p 1 12 | n2 = lduc2ui p 2 13 | n3 = lduc2ui p 3 14 | 15 | ; Collate the results. 16 | r0 = xori n0chk n0 17 | r1 = xori n1chk n1 18 | r2 = xori n2chk n2 19 | r3 = xori n3chk n3 20 | 21 | r0_1 = ori r0 r1 22 | r2_3 = ori r2 r3 23 | 24 | r = ori r0_1 r2_3 25 | reti r 26 | 27 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/lduc2ui.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/ldus2ui.in: -------------------------------------------------------------------------------- 1 | full = immi -249334698 ; 0xf1237456 2 | p = allocp 4 3 | sti full p 0 4 | 5 | n0chk = immi 29782 ; sign_extend(0x7456) 6 | n1chk = immi 61731 ; sign_extend(0xf123) 7 | 8 | n0 = ldus2ui p 0 9 | n1 = ldus2ui p 2 10 | 11 | ; Collate the results. 12 | r0 = xori n0chk n0 13 | r1 = xori n1chk n1 14 | 15 | r = ori r0 r1 16 | reti r 17 | 18 | -------------------------------------------------------------------------------- /lirasm/tests/littleendian/ldus2ui.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/loadstore.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | five = immi 5 3 | sti five ptr 0 4 | three = immi 3 5 | sti three ptr 4 6 | v = ldi ptr 0 7 | u = ldi ptr 4 8 | res = addi u v 9 | reti res 10 | -------------------------------------------------------------------------------- /lirasm/tests/loadstore.out: -------------------------------------------------------------------------------- 1 | Output is: 8 2 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xxx.in: -------------------------------------------------------------------------------- 1 | ; 46340 * 46340 < 2^31, and will not overflow. 2 | big = immi 46340 3 | 4 | res = muli big big 5 | 6 | reti res 7 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xxx.out: -------------------------------------------------------------------------------- 1 | Output is: 2147395600 2 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xxy.in: -------------------------------------------------------------------------------- 1 | ; 1073741823 * 2 < 2^31, and will not overflow. 2 | big = immi 1073741823 3 | two = immi 2 4 | 5 | res = muli big two 6 | 7 | reti res 8 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xxy.out: -------------------------------------------------------------------------------- 1 | Output is: 2147483646 2 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xyy.in: -------------------------------------------------------------------------------- 1 | ; 46340 * 46340 < 2^31, and will not overflow. 2 | big = immi 46340 3 | 4 | res = muli big big 5 | 6 | ; Ensure that 'big' gets its own register and isn't shared with 'res'. 7 | m = allocp 8 8 | sti big m 0 9 | 10 | reti res 11 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xyy.out: -------------------------------------------------------------------------------- 1 | Output is: 2147395600 2 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xyz.in: -------------------------------------------------------------------------------- 1 | ; 1073741823 * 2 < 2^31, and will not overflow. 2 | big = immi 1073741823 3 | two = immi 2 4 | 5 | res = muli big two 6 | 7 | ; Ensure that 'big' and 'two' get their own registers and 8 | ; aren't shared with 'res'. 9 | m = allocp 12 10 | sti big m 0 11 | sti two m 4 12 | 13 | reti res 14 | -------------------------------------------------------------------------------- /lirasm/tests/mul_xyz.out: -------------------------------------------------------------------------------- 1 | Output is: 2147483646 2 | -------------------------------------------------------------------------------- /lirasm/tests/muld.in: -------------------------------------------------------------------------------- 1 | ; Try to exercise as many different possibilities for the register allocator as 2 | ; is feasible. 3 | 4 | p1 = allocp 8 5 | p2 = allocp 8 6 | 7 | d1a = immd 2.0 8 | d1 = muld d1a d1a ; X = X * X 9 | std d1 p1 0 10 | 11 | d2a = immd 2.5 12 | d2b = immd 3.0 13 | d2 = muld d2a d2b ; X = X * Y 14 | std d2b p2 0 15 | std d2 p2 0 16 | 17 | d3a = ldd p1 0 18 | d3b = ldd p2 0 19 | d3 = muld d3a d3b ; X = Y * X 20 | std d3a p2 0 21 | std d3 p2 0 22 | 23 | d4a = ldd p2 0 24 | d4b = ldd p1 0 25 | d4 = muld d4a d4b ; X = Y * Z 26 | std d4a p1 0 27 | std d4b p2 0 28 | std d4 p1 0 29 | 30 | d = ldd p1 0 31 | retd d 32 | -------------------------------------------------------------------------------- /lirasm/tests/muld.out: -------------------------------------------------------------------------------- 1 | Output is: 120 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi 65536 4 | b = immi 32767 5 | c = muljovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | 16 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi.out: -------------------------------------------------------------------------------- 1 | Output is: 2147418112 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_ovf.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi 65536 4 | b = immi 32768 5 | c = muljovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_ovf.out: -------------------------------------------------------------------------------- 1 | Output is: 12345678 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xxx.in: -------------------------------------------------------------------------------- 1 | ; 46340 * 46340 < 2^31, and will not overflow. 2 | big = immi 46340 3 | 4 | res = muljovi big big err 5 | 6 | reti res 7 | 8 | ; ---- Exit route for the error handler. 9 | 10 | err: e = immi -1 11 | reti e 12 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xxx.out: -------------------------------------------------------------------------------- 1 | Output is: 2147395600 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xxy.in: -------------------------------------------------------------------------------- 1 | ; 1073741823 * 2 < 2^31, and will not overflow. 2 | big = immi 1073741823 3 | two = immi 2 4 | 5 | res = muljovi big two err 6 | 7 | reti res 8 | 9 | ; ---- Exit route for the error handler. 10 | 11 | err: e = immi -1 12 | reti e 13 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xxy.out: -------------------------------------------------------------------------------- 1 | Output is: 2147483646 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xyy.in: -------------------------------------------------------------------------------- 1 | ; 46340 * 46340 < 2^31, and will not overflow. 2 | big = immi 46340 3 | 4 | res = muljovi big big err 5 | 6 | ; Ensure that 'big' gets its own register and isn't shared with 'res'. 7 | m = allocp 8 8 | sti big m 0 9 | 10 | reti res 11 | 12 | ; ---- Exit route for the error handler. 13 | 14 | err: e = immi -1 15 | reti e 16 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xyy.out: -------------------------------------------------------------------------------- 1 | Output is: 2147395600 2 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xyz.in: -------------------------------------------------------------------------------- 1 | ; 1073741823 * 2 < 2^31, and will not overflow. 2 | big = immi 1073741823 3 | two = immi 2 4 | 5 | res = muljovi big two err 6 | 7 | ; Ensure that 'big' and 'two' get their own registers and 8 | ; aren't shared with 'res'. 9 | m = allocp 12 10 | sti big m 0 11 | sti two m 4 12 | 13 | reti res 14 | 15 | ; ---- Exit route for the error handler. 16 | 17 | err: e = immi -1 18 | reti e 19 | -------------------------------------------------------------------------------- /lirasm/tests/muljovi_xyz.out: -------------------------------------------------------------------------------- 1 | Output is: 2147483646 2 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xxx.in: -------------------------------------------------------------------------------- 1 | ; 46341 * 46341 >= 2^31, and will overflow. 2 | big = immi 46341 3 | 4 | ; Because 'big' isn't used after mul, it _may_ get allocated to the same 5 | ; register as 'res'. This is the case with the ARM back-end, and that is where 6 | ; this test is important as rX=rX*rX isn't possible on ARMv5 without some 7 | ; trickery. 8 | res = mulxovi big big ; overflow, so we exit here 9 | 10 | ; Store 'res' so it isn't dead. 11 | m = allocp 4 12 | sti res m 0 13 | x ; we don't exit here 14 | 15 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xxx.out: -------------------------------------------------------------------------------- 1 | Exited block on line: 8 2 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xxy.in: -------------------------------------------------------------------------------- 1 | ; 1073741824 * 2 >= 2^31, and will overflow. 2 | big = immi 1073741824 3 | two = immi 2 4 | 5 | ; Because 'big' isn't used after mul, it _may_ get allocated to the same 6 | ; register as 'res'. This is the case with the ARM back-end, and that is where 7 | ; this test is important as rX=rX*rY isn't possible on ARMv5 without some 8 | ; trickery. 9 | res = mulxovi big two ; overflow, so we exit here 10 | 11 | ; Store 'res' so it isn't dead. 12 | m = allocp 4 13 | sti res m 0 14 | x ; we don't exit here 15 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xxy.out: -------------------------------------------------------------------------------- 1 | Exited block on line: 9 2 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xyy.in: -------------------------------------------------------------------------------- 1 | ; 46341 * 46341 >= 2^31, and will overflow. 2 | big = immi 46341 3 | 4 | res = mulxovi big big ; overflow, so we exit here 5 | 6 | ; Ensure that 'big' gets its own register and isn't shared with 'res'. 7 | ; Also store 'res' so it isn't dead. 8 | m = allocp 8 9 | sti big m 0 10 | sti res m 4 11 | x ; we don't exit here 12 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xyy.out: -------------------------------------------------------------------------------- 1 | Exited block on line: 4 2 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xyz.in: -------------------------------------------------------------------------------- 1 | ; 1073741824 * 2 >= 2^31, and will overflow. 2 | big = immi 1073741824 3 | two = immi 2 4 | 5 | res = mulxovi big two ; overflow, so we exit here 6 | 7 | ; Ensure that 'big' and 'two' get their own registers and 8 | ; aren't shared with 'res'. Also store 'res' so it isn't dead. 9 | m = allocp 12 10 | sti big m 0 11 | sti two m 4 12 | sti res m 8 13 | x ; we don't exit here 14 | -------------------------------------------------------------------------------- /lirasm/tests/mulov_xyz.out: -------------------------------------------------------------------------------- 1 | Exited block on line: 5 2 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag1.in: -------------------------------------------------------------------------------- 1 | .begin a 2 | ptr = allocp 8 3 | a = immi 65 4 | sti2c a ptr 0 5 | b = immi 66 6 | sti2c b ptr 1 7 | c = immi 67 8 | sti2c c ptr 2 9 | zero = immi 0 10 | sti2c zero ptr 3 11 | ss = calli puts cdecl ptr 12 | nn = gei ss zero 13 | reti nn 14 | .end 15 | 16 | .begin b 17 | rr = calli a fastcall 18 | reti rr 19 | .end 20 | 21 | .begin main 22 | ans = calli b fastcall 23 | five = immi 5 24 | res = addi five ans 25 | reti res 26 | .end 27 | 28 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag1.out: -------------------------------------------------------------------------------- 1 | ABC 2 | Output is: 6 3 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag2.in: -------------------------------------------------------------------------------- 1 | .begin sinpibytwo 2 | pi = immd 3.14 3 | half = immd 0.5 4 | halfpi = muld pi half 5 | res = calld sin cdecl halfpi 6 | retd res 7 | .end 8 | 9 | .begin main 10 | aa = calld sinpibytwo fastcall 11 | bb = immd 5.53 12 | res = addd aa bb 13 | retd res 14 | .end 15 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag2.out: -------------------------------------------------------------------------------- 1 | Output is: 6.53 2 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag3.in: -------------------------------------------------------------------------------- 1 | ; See bug 541232 for why the params are commented out. 2 | .begin avg 3 | oneh = immi 100 ; should be: p1 = paramp 0 0 4 | twoh = immi 200 ; should be: p2 = paramp 1 0 5 | sum = addi oneh twoh ; should be: sum = addp p1 p2 6 | one = immi 1 7 | avg = rshi sum one 8 | reti avg 9 | .end 10 | 11 | .begin main 12 | oneh = immi 100 13 | twoh = immi 200 14 | res = calli avg fastcall twoh oneh 15 | reti res 16 | .end 17 | -------------------------------------------------------------------------------- /lirasm/tests/multfrag3.out: -------------------------------------------------------------------------------- 1 | Output is: 150 2 | -------------------------------------------------------------------------------- /lirasm/tests/negnot.in: -------------------------------------------------------------------------------- 1 | i = immi 0 2 | a = noti i 3 | b = negi a 4 | reti b 5 | -------------------------------------------------------------------------------- /lirasm/tests/negnot.out: -------------------------------------------------------------------------------- 1 | Output is: 1 2 | -------------------------------------------------------------------------------- /lirasm/tests/random.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/shi.in: -------------------------------------------------------------------------------- 1 | ; Only the bottom 5 bits of the shift amount in lshi/rshi/rshui are used. 2 | 3 | two = immi 2 4 | 5 | sh1 = immi 1 6 | sh2 = immi 33 ; 0010_0001b 7 | sh3 = immi 268435425 ; 0000_1111_1111_1111_1111_1111_1110_0001b 8 | 9 | a1 = lshi two sh1 ; --> 4 10 | a2 = lshi two sh2 ; --> 4 11 | a3 = lshi two sh3 ; --> 4 12 | 13 | b1 = rshi two sh1 ; --> 1 14 | b2 = rshi two sh2 ; --> 1 15 | b3 = rshi two sh3 ; --> 1 16 | 17 | c1 = rshui two sh1 ; --> 1 18 | c2 = rshui two sh2 ; --> 1 19 | c3 = rshui two sh3 ; --> 1 20 | 21 | s0 = immi 0 22 | s1 = addi s0 a1 23 | s2 = addi s1 a2 24 | s3 = addi s2 a3 25 | s4 = addi s3 b1 26 | s5 = addi s4 b2 27 | s6 = addi s5 b3 28 | s7 = addi s6 c1 29 | s8 = addi s7 c2 30 | s9 = addi s8 c2 ; --> 18 31 | 32 | reti s9 33 | -------------------------------------------------------------------------------- /lirasm/tests/shi.out: -------------------------------------------------------------------------------- 1 | Output is: 18 2 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/dhi2i.in: -------------------------------------------------------------------------------- 1 | ; IEEE-754 encodes -0.0 as 0x80000000,00000000 2 | d = immd -0.0 3 | hi = dhi2i d 4 | reti hi 5 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/dhi2i.out: -------------------------------------------------------------------------------- 1 | Output is: -2147483648 2 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/dlo2i.in: -------------------------------------------------------------------------------- 1 | ; IEEE-754 encodes the following constant as 0x3ff00000,ffffffff 2 | d = immd 1.0000009536743162 3 | lo = dlo2i d 4 | reti lo 5 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/dlo2i.out: -------------------------------------------------------------------------------- 1 | Output is: -1 2 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/ii2d.in: -------------------------------------------------------------------------------- 1 | ; It's very difficult to test that the 'lo' part is actually doing anything 2 | ; because it tends to get lost when lirasm dumps the result to the console. 3 | ; By far the easiest way to check this is to use dlo2i and dhi2i to see if we 4 | ; get what we started with (assuming that those instructions work). 5 | 6 | hi = immi 1127219201 ; 0x43300001 (positive, exponent of +52 ... 7 | lo = immi -1 ; 0xffffffff (... mantissa of 0x100001ffffffff) 8 | d = ii2d lo hi 9 | hi2 = dhi2i d 10 | lo2 = dlo2i d 11 | 12 | ; XOR to check for differences, then OR the two results. 0 indicates success, 13 | ; but anything else indicates some kind of loss of data. 14 | rhi = xori hi hi2 15 | rlo = xori lo lo2 16 | 17 | res = ori rhi rlo 18 | 19 | reti res 20 | 21 | -------------------------------------------------------------------------------- /lirasm/tests/softfloat/ii2d.out: -------------------------------------------------------------------------------- 1 | Output is: 0 2 | -------------------------------------------------------------------------------- /lirasm/tests/std2f.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | d = immd -1 3 | ; Store the value twice in consecutive slots to check that it's really stored as 32 bits. 4 | std2f d ptr 4 5 | std2f d ptr 0 6 | d2 = ldf2d ptr 4 7 | retd d2 8 | -------------------------------------------------------------------------------- /lirasm/tests/std2f.out: -------------------------------------------------------------------------------- 1 | Output is: -1 2 | -------------------------------------------------------------------------------- /lirasm/tests/subd.in: -------------------------------------------------------------------------------- 1 | ; Try to exercise as many different possibilities for the register allocator as 2 | ; is feasible. 3 | 4 | p1 = allocp 8 5 | p2 = allocp 8 6 | 7 | d1a = immd 1.5 8 | d1 = subd d1a d1a ; X = X - X 9 | std d1 p1 0 10 | 11 | d2a = immd 2.5 12 | d2b = immd 3.0 13 | d2 = subd d2a d2b ; X = X - Y 14 | std d2b p2 0 15 | std d2 p2 0 16 | 17 | d3a = ldd p1 0 18 | d3b = ldd p2 0 19 | d3 = subd d3a d3b ; X = Y - X 20 | std d3a p2 0 21 | std d3 p2 0 22 | 23 | d4a = ldd p2 0 24 | d4b = ldd p1 0 25 | d4 = subd d4a d4b ; X = Y - Z 26 | std d4a p1 0 27 | std d4b p2 0 28 | std d4 p1 0 29 | 30 | d = ldd p1 0 31 | retd d 32 | -------------------------------------------------------------------------------- /lirasm/tests/subd.out: -------------------------------------------------------------------------------- 1 | Output is: 0.5 2 | -------------------------------------------------------------------------------- /lirasm/tests/subjovi.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi -2147483647 4 | b = immi 1 5 | c = subjovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | 16 | -------------------------------------------------------------------------------- /lirasm/tests/subjovi.out: -------------------------------------------------------------------------------- 1 | Output is: -2147483648 2 | -------------------------------------------------------------------------------- /lirasm/tests/subjovi_ovf.in: -------------------------------------------------------------------------------- 1 | ptr = allocp 8 2 | 3 | a = immi -2147483647 4 | b = immi 2 5 | c = subjovi a b ovf 6 | sti c ptr 0 7 | 8 | j done 9 | 10 | ovf: i = immi 12345678 11 | sti i ptr 0 12 | 13 | done: res = ldi ptr 0 14 | reti res 15 | -------------------------------------------------------------------------------- /lirasm/tests/subjovi_ovf.out: -------------------------------------------------------------------------------- 1 | Output is: 12345678 2 | -------------------------------------------------------------------------------- /nanojit/Allocator.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #include "nanojit.h" 41 | 42 | #ifdef FEATURE_NANOJIT 43 | 44 | namespace nanojit 45 | { 46 | Allocator::Allocator() 47 | : current_chunk(NULL) 48 | , current_top(NULL) 49 | , current_limit(NULL) 50 | { } 51 | 52 | Allocator::~Allocator() 53 | { 54 | reset(); 55 | } 56 | 57 | void Allocator::reset() 58 | { 59 | Chunk *c = current_chunk; 60 | while (c) { 61 | Chunk *prev = c->prev; 62 | freeChunk(c); 63 | c = prev; 64 | } 65 | current_chunk = NULL; 66 | current_top = NULL; 67 | current_limit = NULL; 68 | postReset(); 69 | } 70 | 71 | void* Allocator::allocSlow(size_t nbytes, bool fallible) 72 | { 73 | NanoAssert((nbytes & 7) == 0); 74 | if (fill(nbytes, fallible)) { 75 | NanoAssert(current_top + nbytes <= current_limit); 76 | void* p = current_top; 77 | current_top += nbytes; 78 | return p; 79 | } 80 | return NULL; 81 | } 82 | 83 | bool Allocator::fill(size_t nbytes, bool fallible) 84 | { 85 | if (nbytes < MIN_CHUNK_SZB) 86 | nbytes = MIN_CHUNK_SZB; 87 | size_t chunkbytes = sizeof(Chunk) + nbytes - sizeof(int64_t); 88 | void* mem = allocChunk(chunkbytes, fallible); 89 | if (mem) { 90 | Chunk* chunk = (Chunk*) mem; 91 | chunk->prev = current_chunk; 92 | current_chunk = chunk; 93 | current_top = (char*)chunk->data; 94 | current_limit = (char*)mem + chunkbytes; 95 | return true; 96 | } else { 97 | NanoAssert(fallible); 98 | return false; 99 | } 100 | } 101 | } 102 | 103 | #endif // FEATURE_NANOJIT 104 | -------------------------------------------------------------------------------- /nanojit/Allocator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2009 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef __nanojit_Allocator__ 41 | #define __nanojit_Allocator__ 42 | 43 | namespace nanojit 44 | { 45 | /** 46 | * Allocator is a bump-pointer allocator with an SPI for getting more 47 | * memory from embedder-implemented allocator, such as malloc()/free(). 48 | * 49 | * alloc() never returns NULL. The implementation of allocChunk() 50 | * is expected to perform a longjmp or exception when an allocation can't 51 | * proceed. fallibleAlloc() (and fallibleAllocChunk()) may return NULL. 52 | * They should be used for large allocations whose failure can be handled 53 | * without too much difficulty. 54 | */ 55 | class Allocator { 56 | public: 57 | Allocator(); 58 | ~Allocator(); 59 | 60 | // Usable space in the minimum chunk size; there are also a few bytes 61 | // used for administration. 62 | static const size_t MIN_CHUNK_SZB = 2000; 63 | 64 | void reset(); 65 | 66 | /** alloc memory, never return null. */ 67 | void* alloc(size_t nbytes) { 68 | void* p; 69 | nbytes = (nbytes + 7) & ~7; // round up 70 | if (current_top + nbytes <= current_limit) { 71 | p = current_top; 72 | current_top += nbytes; 73 | } else { 74 | p = allocSlow(nbytes, /* fallible = */false); 75 | NanoAssert(p); 76 | } 77 | return p; 78 | } 79 | 80 | /** alloc memory, maybe return null. */ 81 | void* fallibleAlloc(size_t nbytes) { 82 | void* p; 83 | nbytes = (nbytes + 7) & ~7; // round up 84 | if (current_top + nbytes <= current_limit) { 85 | p = current_top; 86 | current_top += nbytes; 87 | } else { 88 | p = allocSlow(nbytes, /* fallible = */true); 89 | } 90 | return p; 91 | } 92 | 93 | protected: 94 | void* allocSlow(size_t nbytes, bool fallible = false); 95 | bool fill(size_t minbytes, bool fallible); 96 | 97 | class Chunk { 98 | public: 99 | Chunk* prev; 100 | int64_t data[1]; // int64_t forces 8-byte alignment. 101 | }; 102 | 103 | Chunk* current_chunk; 104 | char* current_top; 105 | char* current_limit; 106 | 107 | // allocator SPI 108 | 109 | /** allocate another block from a host provided allocator */ 110 | void* allocChunk(size_t nbytes, bool fallible); 111 | 112 | /** free back to the same allocator */ 113 | void freeChunk(void*); 114 | 115 | /** hook for post-reset action. */ 116 | void postReset(); 117 | }; 118 | } 119 | 120 | /** global new overload enabling this pattern: new (allocator) T(...) */ 121 | inline void* operator new(size_t size, nanojit::Allocator &a) { 122 | return a.alloc(size); 123 | } 124 | 125 | /** global new overload enabling this pattern: new (allocator) T(...) */ 126 | inline void* operator new(size_t size, nanojit::Allocator *a) { 127 | return a->alloc(size); 128 | } 129 | 130 | /** global new[] overload enabling this pattern: new (allocator) T[] */ 131 | inline void* operator new[](size_t size, nanojit::Allocator& a) { 132 | return a.alloc(size); 133 | } 134 | 135 | /** global new[] overload enabling this pattern: new (allocator) T[] */ 136 | inline void* operator new[](size_t size, nanojit::Allocator* a) { 137 | return a->alloc(size); 138 | } 139 | 140 | #endif // __nanojit_Allocator__ 141 | -------------------------------------------------------------------------------- /nanojit/CodeAlloc.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef __nanojit_CodeAlloc__ 41 | #define __nanojit_CodeAlloc__ 42 | 43 | namespace nanojit 44 | { 45 | /** 46 | * CodeList is a single block of code. The next field is used to 47 | * form linked lists of non-contiguous blocks of code. Clients use CodeList* 48 | * to point to the first block in a list. 49 | */ 50 | class CodeList 51 | { 52 | friend class CodeAlloc; 53 | 54 | /** for making singly linked lists of blocks in any order */ 55 | CodeList* next; 56 | 57 | /** adjacent block at lower address. This field plus higher 58 | form a doubly linked list of blocks in address order, used 59 | for splitting and coalescing blocks. */ 60 | CodeList* lower; 61 | 62 | /** pointer to the heapblock terminal that represents the code chunk containing this block */ 63 | CodeList* terminator; 64 | 65 | /** true if block is free, false otherwise */ 66 | bool isFree; 67 | 68 | /** (only valid for terminator blocks). Set true just before calling 69 | * markCodeChunkExec() and false just after markCodeChunkWrite() */ 70 | bool isExec; 71 | 72 | union { 73 | // this union is used in leu of pointer punning in code 74 | // the end of this block is always the address of the next higher block 75 | CodeList* higher; // adjacent block at higher address 76 | NIns* end; // points just past the end 77 | }; 78 | 79 | /** code holds this block's payload of binary code, from 80 | here to this->end */ 81 | NIns code[1]; // more follows 82 | 83 | /** return the starting address for this block only */ 84 | NIns* start() { return &code[0]; } 85 | 86 | /** return just the usable size of this block */ 87 | size_t size() const { return uintptr_t(end) - uintptr_t(&code[0]); } 88 | 89 | /** return the whole size of this block including overhead */ 90 | size_t blockSize() const { return uintptr_t(end) - uintptr_t(this); } 91 | 92 | public: 93 | /** true is the given NIns is contained within this block */ 94 | bool isInBlock(NIns* n) { return (n >= this->start() && n < this->end); } 95 | }; 96 | 97 | /** 98 | * Code memory allocator is a long lived manager for many code blocks that 99 | * manages interaction with an underlying code memory allocator, 100 | * sets page permissions. CodeAlloc provides APIs for allocating and freeing 101 | * individual blocks of code memory (for methods, stubs, or compiled 102 | * traces), static functions for managing lists of allocated code, and has 103 | * a few pure virtual methods that embedders must implement to provide 104 | * memory to the allocator. 105 | * 106 | * A "chunk" is a region of memory obtained from allocCodeChunk; it must 107 | * be page aligned and be a multiple of the system page size. 108 | * 109 | * A "block" is a region of memory within a chunk. It can be arbitrarily 110 | * sized and aligned, but is always contained within a single chunk. 111 | * class CodeList represents one block; the members of CodeList track the 112 | * extent of the block and support creating lists of blocks. 113 | * 114 | * The allocator coalesces free blocks when it can, in free(), but never 115 | * coalesces chunks. 116 | */ 117 | class CodeAlloc 118 | { 119 | static const size_t sizeofMinBlock = offsetof(CodeList, code); 120 | static const size_t minAllocSize = LARGEST_UNDERRUN_PROT; 121 | 122 | // Return the number of bytes needed for the header of 'n' blocks 123 | static size_t headerSpaceFor(uint32_t nbrBlks) { return nbrBlks * sizeofMinBlock; } 124 | 125 | // Return the number of bytes needed in order to safely construct 'n' blocks 126 | static size_t blkSpaceFor(uint32_t nbrBlks) { return (nbrBlks * minAllocSize) + headerSpaceFor(nbrBlks); } 127 | 128 | /** Terminator blocks. All active and free allocations 129 | are reachable by traversing this chain and each 130 | element's lower chain. */ 131 | CodeList* heapblocks; 132 | 133 | /** Reusable blocks. */ 134 | CodeList* availblocks; 135 | size_t totalAllocated; 136 | 137 | /** Cached value of VMPI_getVMPageSize */ 138 | const size_t bytesPerPage; 139 | 140 | /** Number of bytes to request from VMPI layer, always a multiple of the page size */ 141 | const size_t bytesPerAlloc; 142 | 143 | /** remove one block from a list */ 144 | static CodeList* removeBlock(CodeList* &list); 145 | 146 | /** add one block to a list */ 147 | static void addBlock(CodeList* &blocks, CodeList* b); 148 | 149 | /** compute the CodeList pointer from a [start, end) range */ 150 | static CodeList* getBlock(NIns* start, NIns* end); 151 | 152 | /** add raw memory to the free list */ 153 | void addMem(); 154 | 155 | /** make sure all the higher/lower pointers are correct for every block */ 156 | void sanity_check(); 157 | 158 | /** find the beginning of the heapblock terminated by term */ 159 | CodeList* firstBlock(CodeList* term); 160 | 161 | // 162 | // CodeAlloc's SPI (Service Provider Interface). Implementations must be 163 | // defined by nanojit embedder. Allocation failures should cause an exception 164 | // or longjmp; nanojit intentionally does not check for null. 165 | // 166 | 167 | /** allocate nbytes of memory to hold code. Never return null! */ 168 | void* allocCodeChunk(size_t nbytes); 169 | 170 | /** free a block previously allocated by allocCodeMem. nbytes will 171 | * match the previous allocCodeMem, but is provided here as well 172 | * to mirror the mmap()/munmap() api. markCodeChunkWrite() will have 173 | * been called if necessary, so it is not necessary for freeCodeChunk() 174 | * to do it again. */ 175 | void freeCodeChunk(void* addr, size_t nbytes); 176 | 177 | /** make this specific extent ready to execute (might remove write) */ 178 | void markCodeChunkExec(void* addr, size_t nbytes); 179 | 180 | /** make this extent ready to modify (might remove exec) */ 181 | void markCodeChunkWrite(void* addr, size_t nbytes); 182 | 183 | public: 184 | CodeAlloc(); 185 | ~CodeAlloc(); 186 | 187 | /** return all the memory allocated through this allocator to the gcheap. */ 188 | void reset(); 189 | 190 | /** allocate some memory (up to 'byteLimit' bytes) for code returning pointers to the region. A zero 'byteLimit' means no limit */ 191 | void alloc(NIns* &start, NIns* &end, size_t byteLimit); 192 | 193 | /** free a block of memory previously returned by alloc() */ 194 | void free(NIns* start, NIns* end); 195 | 196 | /** free several blocks */ 197 | void freeAll(CodeList* &code); 198 | 199 | /** flush the icache for all code in the list, before executing */ 200 | static void flushICache(CodeList* &blocks); 201 | 202 | /** flush the icache for a specific extent */ 203 | static void flushICache(void *start, size_t len); 204 | 205 | /** add the ranges [start, holeStart) and [holeEnd, end) to code, and 206 | free [holeStart, holeEnd) if the hole is >= minsize */ 207 | void addRemainder(CodeList* &code, NIns* start, NIns* end, NIns* holeStart, NIns* holeEnd); 208 | 209 | /** add a block previously returned by alloc(), to code */ 210 | static void add(CodeList* &code, NIns* start, NIns* end); 211 | 212 | /** return the number of bytes in all the code blocks in "code", including block overhead */ 213 | #ifdef PERFM 214 | static size_t size(const CodeList* code); 215 | #endif 216 | 217 | /** return the total number of bytes held by this CodeAlloc. */ 218 | size_t size(); 219 | 220 | /** print out stats about heap usage */ 221 | void logStats(); 222 | 223 | /** protect all code managed by this CodeAlloc */ 224 | void markAllExec(); 225 | 226 | /** protect all mem in the block list */ 227 | void markExec(CodeList* &blocks); 228 | 229 | /** protect an entire chunk */ 230 | void markChunkExec(CodeList* term); 231 | 232 | /** unprotect the code chunk containing just this one block */ 233 | void markBlockWrite(CodeList* b); 234 | }; 235 | } 236 | 237 | #endif // __nanojit_CodeAlloc__ 238 | -------------------------------------------------------------------------------- /nanojit/Containers.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #include "nanojit.h" 41 | 42 | #ifdef FEATURE_NANOJIT 43 | 44 | namespace nanojit 45 | { 46 | BitSet::BitSet(Allocator& allocator, int nbits) 47 | : allocator(allocator) 48 | , cap((nbits+63)>>6) 49 | , bits((int64_t*)allocator.alloc(cap * sizeof(int64_t))) 50 | { 51 | reset(); 52 | } 53 | 54 | void BitSet::reset() 55 | { 56 | for (int i=0, n=cap; i < n; i++) 57 | bits[i] = 0; 58 | } 59 | 60 | bool BitSet::setFrom(BitSet& other) 61 | { 62 | int c = other.cap; 63 | if (c > cap) 64 | grow(c); 65 | int64_t *bits = this->bits; 66 | int64_t *otherbits = other.bits; 67 | int64_t newbits = 0; 68 | for (int i=0; i < c; i++) { 69 | int64_t b = bits[i]; 70 | int64_t b2 = otherbits[i]; 71 | newbits |= b2 & ~b; // bits in b2 that are not in b 72 | bits[i] = b|b2; 73 | } 74 | return newbits != 0; 75 | } 76 | 77 | /** keep doubling the bitset length until w fits */ 78 | void BitSet::grow(int w) 79 | { 80 | int cap2 = cap; 81 | do { 82 | cap2 <<= 1; 83 | } while (w > cap2); 84 | int64_t *bits2 = (int64_t*) allocator.alloc(cap2 * sizeof(int64_t)); 85 | int j=0; 86 | for (; j < cap; j++) 87 | bits2[j] = bits[j]; 88 | for (; j < cap2; j++) 89 | bits2[j] = 0; 90 | cap = cap2; 91 | bits = bits2; 92 | } 93 | } 94 | 95 | #endif // FEATURE_NANOJIT 96 | -------------------------------------------------------------------------------- /nanojit/Fragmento.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * Mozilla TraceMonkey Team 26 | * Asko Tontti 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * either the GNU General Public License Version 2 or later (the "GPL"), or 30 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 31 | * in which case the provisions of the GPL or the LGPL are applicable instead 32 | * of those above. If you wish to allow use of your version of this file only 33 | * under the terms of either the GPL or the LGPL, and not to allow others to 34 | * use your version of this file under the terms of the MPL, indicate your 35 | * decision by deleting the provisions above and replace them with the notice 36 | * and other provisions required by the GPL or the LGPL. If you do not delete 37 | * the provisions above, a recipient may use your version of this file under 38 | * the terms of any one of the MPL, the GPL or the LGPL. 39 | * 40 | * ***** END LICENSE BLOCK ***** */ 41 | 42 | #include "nanojit.h" 43 | 44 | namespace nanojit 45 | { 46 | #ifdef FEATURE_NANOJIT 47 | 48 | using namespace avmplus; 49 | 50 | // 51 | // Fragment 52 | // 53 | Fragment::Fragment(const void* _ip 54 | verbose_only(, uint32_t profFragID)) 55 | : 56 | lirbuf(NULL), 57 | lastIns(NULL), 58 | ip(_ip), 59 | recordAttempts(0), 60 | fragEntry(NULL), 61 | verbose_only( loopLabel(NULL), ) 62 | verbose_only( profFragID(profFragID), ) 63 | verbose_only( profCount(0), ) 64 | verbose_only( nStaticExits(0), ) 65 | verbose_only( nCodeBytes(0), ) 66 | verbose_only( nExitBytes(0), ) 67 | verbose_only( guardNumberer(1), ) 68 | verbose_only( guardsForFrag(NULL), ) 69 | _code(NULL), 70 | _hits(0) 71 | { 72 | // when frag profiling is enabled, profFragID should be >= 1, 73 | // else it should be zero. However, there's no way to assert 74 | // that here since there's no way to determine whether frag 75 | // profiling is enabled. 76 | } 77 | #endif /* FEATURE_NANOJIT */ 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /nanojit/Fragmento.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * Mozilla TraceMonkey Team 26 | * Asko Tontti 27 | * 28 | * Alternatively, the contents of this file may be used under the terms of 29 | * either the GNU General Public License Version 2 or later (the "GPL"), or 30 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 31 | * in which case the provisions of the GPL or the LGPL are applicable instead 32 | * of those above. If you wish to allow use of your version of this file only 33 | * under the terms of either the GPL or the LGPL, and not to allow others to 34 | * use your version of this file under the terms of the MPL, indicate your 35 | * decision by deleting the provisions above and replace them with the notice 36 | * and other provisions required by the GPL or the LGPL. If you do not delete 37 | * the provisions above, a recipient may use your version of this file under 38 | * the terms of any one of the MPL, the GPL or the LGPL. 39 | * 40 | * ***** END LICENSE BLOCK ***** */ 41 | 42 | 43 | #ifndef __nanojit_Fragmento__ 44 | #define __nanojit_Fragmento__ 45 | 46 | namespace nanojit 47 | { 48 | struct GuardRecord; 49 | 50 | /** 51 | * Fragments are linear sequences of native code that have a single entry 52 | * point at the start of the fragment and may have one or more exit points 53 | * 54 | * It may turn out that that this arrangement causes too much traffic 55 | * between d and i-caches and that we need to carve up the structure differently. 56 | */ 57 | class Fragment 58 | { 59 | public: 60 | Fragment(const void* 61 | verbose_only(, uint32_t profFragID)); 62 | 63 | NIns* code() { return _code; } 64 | void setCode(NIns* codee) { _code = codee; } 65 | int32_t& hits() { return _hits; } 66 | 67 | LirBuffer* lirbuf; 68 | LIns* lastIns; 69 | 70 | const void* ip; 71 | uint32_t recordAttempts; 72 | NIns* fragEntry; 73 | 74 | // for fragment entry and exit profiling. See detailed 75 | // how-to-use comment below. 76 | verbose_only( LIns* loopLabel; ) // where's the loop top? 77 | verbose_only( uint32_t profFragID; ) 78 | verbose_only( uint32_t profCount; ) 79 | verbose_only( uint32_t nStaticExits; ) 80 | verbose_only( size_t nCodeBytes; ) 81 | verbose_only( size_t nExitBytes; ) 82 | verbose_only( uint32_t guardNumberer; ) 83 | verbose_only( GuardRecord* guardsForFrag; ) 84 | 85 | private: 86 | NIns* _code; // ptr to start of code 87 | int32_t _hits; 88 | }; 89 | } 90 | 91 | /* 92 | * How to use fragment profiling 93 | * 94 | * Fragprofiling adds code to count how many times each fragment is 95 | * entered, and how many times each guard (exit) is taken. Using this 96 | * it's possible to easily find which fragments are hot, which ones 97 | * typically exit early, etc. The fragprofiler also gathers some 98 | * simple static info: for each fragment, the number of code bytes, 99 | * number of exit-block bytes, and number of guards (exits). 100 | * 101 | * Fragments and guards are given unique IDs (FragID, GuardID) which 102 | * are shown in debug printouts, so as to facilitate navigating from 103 | * the accumulated statistics to the associated bits of code. 104 | * GuardIDs are issued automatically, but FragIDs you must supply when 105 | * calling Fragment::Fragment. Supply values >= 1, and supply a 106 | * different value for each new fragment (doesn't matter what, they 107 | * just have to be unique and >= 1); else 108 | * js_FragProfiling_FragFinalizer will assert. 109 | * 110 | * How to use/embed: 111 | * 112 | * - use a debug build (one with NJ_VERBOSE). Without it, none of 113 | * this code is compiled in. 114 | * 115 | * - set LC_FragProfile in the lcbits of the LogControl* object handed 116 | * to Nanojit 117 | * 118 | * When enabled, Fragment::profCount is incremented every time the 119 | * fragment is entered, and GuardRecord::profCount is incremented 120 | * every time that guard exits. However, NJ has no way to know where 121 | * the fragment entry/loopback point is. So you must set 122 | * Fragment::loopLabel before running the assembler, so as to indicate 123 | * where the fragment-entry counter increment should be placed. If 124 | * the fragment does not naturally have a loop label then you will 125 | * need to artificially add one. 126 | * 127 | * It is the embedder's problem to fish out, collate and present the 128 | * accumulated stats at the end of the Fragment's lifetime. A 129 | * Fragment contains stats indicating its entry count and static code 130 | * sizes. It also has a ::guardsForFrag field, which is a linked list 131 | * of GuardRecords, and by traversing them you can get hold of the 132 | * exit counts. 133 | */ 134 | 135 | #endif // __nanojit_Fragmento__ 136 | -------------------------------------------------------------------------------- /nanojit/Native.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | 41 | #ifndef __nanojit_Native__ 42 | #define __nanojit_Native__ 43 | 44 | // define PEDANTIC=1 to ignore specialized forms, force general forms 45 | // for everything, far branches, extra page-linking, etc. This will 46 | // flush out many corner cases. 47 | 48 | #define PEDANTIC 0 49 | #if PEDANTIC 50 | # define UNLESS_PEDANTIC(...) 51 | # define IF_PEDANTIC(...) __VA_ARGS__ 52 | #else 53 | # define UNLESS_PEDANTIC(...) __VA_ARGS__ 54 | # define IF_PEDANTIC(...) 55 | #endif 56 | 57 | #ifdef NANOJIT_IA32 58 | #include "Nativei386.h" 59 | #elif defined(NANOJIT_ARM) 60 | #include "NativeARM.h" 61 | #elif defined(NANOJIT_PPC) 62 | #include "NativePPC.h" 63 | #elif defined(NANOJIT_SPARC) 64 | #include "NativeSparc.h" 65 | #elif defined(NANOJIT_X64) 66 | #include "NativeX64.h" 67 | #elif defined(NANOJIT_SH4) 68 | #include "NativeSH4.h" 69 | #elif defined(NANOJIT_MIPS) 70 | #include "NativeMIPS.h" 71 | #else 72 | #error "unknown nanojit architecture" 73 | #endif 74 | 75 | #ifndef NJ_USES_IMMD_POOL 76 | # define NJ_USES_IMMD_POOL 0 77 | #endif 78 | 79 | #ifndef NJ_JTBL_SUPPORTED 80 | # define NJ_JTBL_SUPPORTED 0 81 | #endif 82 | 83 | #ifndef NJ_EXPANDED_LOADSTORE_SUPPORTED 84 | # define NJ_EXPANDED_LOADSTORE_SUPPORTED 0 85 | #endif 86 | 87 | #ifndef NJ_F2I_SUPPORTED 88 | # define NJ_F2I_SUPPORTED 0 89 | #endif 90 | 91 | #ifndef NJ_SOFTFLOAT_SUPPORTED 92 | # define NJ_SOFTFLOAT_SUPPORTED 0 93 | #endif 94 | 95 | #ifndef NJ_DIVI_SUPPORTED 96 | # define NJ_DIVI_SUPPORTED 0 97 | #endif 98 | 99 | #if NJ_SOFTFLOAT_SUPPORTED 100 | #define CASESF(x) case x 101 | #else 102 | #define CASESF(x) 103 | #endif 104 | 105 | namespace nanojit { 106 | 107 | class Fragment; 108 | struct SideExit; 109 | struct SwitchInfo; 110 | 111 | struct GuardRecord 112 | { 113 | void* jmp; 114 | GuardRecord* next; 115 | SideExit* exit; 116 | // profiling stuff 117 | verbose_only( uint32_t profCount; ) 118 | verbose_only( uint32_t profGuardID; ) 119 | verbose_only( GuardRecord* nextInFrag; ) 120 | }; 121 | 122 | struct SideExit 123 | { 124 | GuardRecord* guards; 125 | Fragment* from; 126 | Fragment* target; 127 | SwitchInfo* switchInfo; 128 | 129 | void addGuard(GuardRecord* gr) 130 | { 131 | NanoAssert(gr->next == NULL); 132 | NanoAssert(guards != gr); 133 | gr->next = guards; 134 | guards = gr; 135 | } 136 | }; 137 | } 138 | 139 | #define isSPorFP(r) ( (r)==SP || (r)==FP ) 140 | 141 | #ifdef NJ_NO_VARIADIC_MACROS 142 | static void asm_output(const char *f, ...) {} 143 | #define gpn(r) regNames[(REGNUM(n))] 144 | #elif defined(NJ_VERBOSE) 145 | inline char cvaltoa(unsigned char u) { 146 | return u<10 ? u+'0' : u+'a'-10; 147 | } 148 | 149 | inline char* appendHexVals(char* str, char* valFrom, char* valTo) { 150 | NanoAssert(valFrom <= valTo); 151 | str += VMPI_strlen(str); 152 | for(char* ch = valFrom; ch < valTo; ch++) { 153 | unsigned char u = (unsigned char)*ch; 154 | *str++ = cvaltoa(u >> 4); 155 | *str++ = cvaltoa(u & 0xf); 156 | *str++ = ' '; 157 | } 158 | *str = '\0'; 159 | return str; 160 | } 161 | 162 | inline char* padTo(char* str, int n, char c=' ') { 163 | char* start = str + VMPI_strlen(str); 164 | char* end = &str[n]; 165 | while(start < end) 166 | *start++ = c; 167 | *end = '\0'; 168 | return end; 169 | } 170 | 171 | // Used for printing native instructions. Like Assembler::outputf(), 172 | // but only outputs if LC_Native is set. Also prepends the output 173 | // with the address of the current native instruction. 174 | #define asm_output(...) do { \ 175 | if (_logc->lcbits & LC_Native) { \ 176 | outline[0]='\0'; \ 177 | VMPI_sprintf(outline, "%p ", _nIns); \ 178 | if (_logc->lcbits & LC_Bytes) { \ 179 | appendHexVals(outline, (char*)_nIns, (char*)_nInsAfter); \ 180 | padTo(outline, 3*15); \ 181 | } \ 182 | VMPI_sprintf(outline + VMPI_strlen(outline), ##__VA_ARGS__); \ 183 | output(); \ 184 | _nInsAfter = _nIns; \ 185 | } \ 186 | } while (0) /* no semi */ 187 | #define gpn(r) regNames[(REGNUM(r))] 188 | #else 189 | #define asm_output(...) 190 | #define gpn(r) 191 | #endif /* NJ_VERBOSE */ 192 | 193 | #endif // __nanojit_Native__ 194 | -------------------------------------------------------------------------------- /nanojit/NativeCommon.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2008 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef __nanojit_NativeCommon__ 41 | #define __nanojit_NativeCommon__ 42 | 43 | namespace nanojit 44 | { 45 | // In debug builds, Register is defined as a non-integer type to avoid 46 | // possible mix-ups with RegisterMask and integer offsets. In non-debug 47 | // builds, it's defined as an integer just in case some compilers fail to 48 | // optimize single-element structs in the obvious way. 49 | // 50 | // Note that in either case, a Register can be initialized like so: 51 | // 52 | // Register r = { 0 }; 53 | // 54 | // In the debug case it's a struct initializer, in the non-debug case it's 55 | // a scalar initializer. 56 | // 57 | // XXX: The exception to all the above is that if NJ_USE_UINT32_REGISTER 58 | // is defined, the back-end is responsible for defining its own Register 59 | // type, which will probably be an enum. This is just to give all the 60 | // back-ends a chance to transition smoothly. 61 | #if defined(NJ_USE_UINT32_REGISTER) 62 | #define REGNUM(r) (r) 63 | 64 | #elif defined(DEBUG) || defined(__SUNPRO_CC) 65 | // Always use struct declaration for 'Register' with 66 | // Solaris Studio C++ compiler, because it has a bug: 67 | // Scalar type can not be initialized by '{1}'. 68 | // See bug 603560. 69 | 70 | struct Register { 71 | uint32_t n; // the register number 72 | }; 73 | 74 | static inline uint32_t REGNUM(Register r) { 75 | return r.n; 76 | } 77 | 78 | static inline Register operator+(Register r, int c) 79 | { 80 | r.n += c; 81 | return r; 82 | } 83 | 84 | static inline bool operator==(Register r1, Register r2) 85 | { 86 | return r1.n == r2.n; 87 | } 88 | 89 | static inline bool operator!=(Register r1, Register r2) 90 | { 91 | return r1.n != r2.n; 92 | } 93 | 94 | static inline bool operator<=(Register r1, Register r2) 95 | { 96 | return r1.n <= r2.n; 97 | } 98 | 99 | static inline bool operator<(Register r1, Register r2) 100 | { 101 | return r1.n < r2.n; 102 | } 103 | 104 | static inline bool operator>=(Register r1, Register r2) 105 | { 106 | return r1.n >= r2.n; 107 | } 108 | 109 | static inline bool operator>(Register r1, Register r2) 110 | { 111 | return r1.n > r2.n; 112 | } 113 | #else 114 | typedef uint32_t Register; 115 | 116 | static inline uint32_t REGNUM(Register r) { 117 | return r; 118 | } 119 | #endif 120 | } // namespace nanojit 121 | 122 | #endif // __nanojit_NativeCommon__ 123 | -------------------------------------------------------------------------------- /nanojit/RegAlloc.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #include "nanojit.h" 41 | 42 | namespace nanojit 43 | { 44 | #ifdef FEATURE_NANOJIT 45 | 46 | #ifdef _DEBUG 47 | 48 | bool RegAlloc::isConsistent(Register r, LIns* i) const 49 | { 50 | NanoAssert(r != deprecated_UnknownReg); 51 | return (isFree(r) && !getActive(r) && !i) || 52 | (!isFree(r) && getActive(r)== i && i ); 53 | } 54 | 55 | #endif /*DEBUG*/ 56 | #endif /* FEATURE_NANOJIT */ 57 | } 58 | -------------------------------------------------------------------------------- /nanojit/RegAlloc.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | 41 | #ifndef __nanojit_RegAlloc__ 42 | #define __nanojit_RegAlloc__ 43 | 44 | 45 | namespace nanojit 46 | { 47 | class RegAlloc 48 | { 49 | public: 50 | RegAlloc() 51 | { 52 | clear(); 53 | } 54 | 55 | void clear() 56 | { 57 | VMPI_memset(this, 0, sizeof(*this)); 58 | } 59 | 60 | bool isFree(Register r) const 61 | { 62 | NanoAssert(r != deprecated_UnknownReg); 63 | return (free & rmask(r)) != 0; 64 | } 65 | 66 | void addFree(Register r) 67 | { 68 | NanoAssert(!isFree(r)); 69 | free |= rmask(r); 70 | } 71 | 72 | void removeFree(Register r) 73 | { 74 | NanoAssert(isFree(r)); 75 | free &= ~rmask(r); 76 | } 77 | 78 | void addActive(Register r, LIns* v) 79 | { 80 | // Count++; 81 | NanoAssert(v); 82 | NanoAssert(r != deprecated_UnknownReg); 83 | NanoAssert(active[REGNUM(r)] == NULL); 84 | active[REGNUM(r)] = v; 85 | useActive(r); 86 | } 87 | 88 | void useActive(Register r) 89 | { 90 | NanoAssert(r != deprecated_UnknownReg); 91 | NanoAssert(active[REGNUM(r)] != NULL); 92 | usepri[REGNUM(r)] = priority++; 93 | } 94 | 95 | void removeActive(Register r) 96 | { 97 | //registerReleaseCount++; 98 | NanoAssert(r != deprecated_UnknownReg); 99 | NanoAssert(active[REGNUM(r)] != NULL); 100 | 101 | // remove the given register from the active list 102 | active[REGNUM(r)] = NULL; 103 | } 104 | 105 | void retire(Register r) 106 | { 107 | NanoAssert(r != deprecated_UnknownReg); 108 | NanoAssert(active[REGNUM(r)] != NULL); 109 | active[REGNUM(r)] = NULL; 110 | free |= rmask(r); 111 | } 112 | 113 | int32_t getPriority(Register r) { 114 | NanoAssert(r != deprecated_UnknownReg && active[REGNUM(r)]); 115 | return usepri[REGNUM(r)]; 116 | } 117 | 118 | LIns* getActive(Register r) const { 119 | NanoAssert(r != deprecated_UnknownReg); 120 | return active[REGNUM(r)]; 121 | } 122 | 123 | // Return a mask containing the active registers. For each register 124 | // in this set, getActive(register) will be a nonzero LIns pointer. 125 | RegisterMask activeMask() const { 126 | return ~free & managed; 127 | } 128 | 129 | debug_only( bool isConsistent(Register r, LIns* v) const; ) 130 | 131 | // Some basics: 132 | // 133 | // - 'active' indicates which registers are active at a particular 134 | // point, and for each active register, which instruction 135 | // defines the value it holds. At the start of register 136 | // allocation no registers are active. 137 | // 138 | // - 'free' indicates which registers are free at a particular point 139 | // and thus available for use. At the start of register 140 | // allocation most registers are free; those that are not 141 | // aren't available for general use, e.g. the stack pointer and 142 | // frame pointer registers. 143 | // 144 | // - 'managed' is exactly this list of initially free registers, 145 | // ie. the registers managed by the register allocator. 146 | // 147 | // - Each LIns has a "reservation" which includes a register value, 148 | // 'reg'. Combined with 'active', this provides a two-way 149 | // mapping between registers and LIR instructions. 150 | // 151 | // - Invariant 1: each register must be in exactly one of the 152 | // following states at all times: unmanaged, free, or active. 153 | // In terms of the relevant fields: 154 | // 155 | // * A register in 'managed' must be in 'active' or 'free' but 156 | // not both. 157 | // 158 | // * A register not in 'managed' must be in neither 'active' nor 159 | // 'free'. 160 | // 161 | // - Invariant 2: the two-way mapping between active registers and 162 | // their defining instructions must always hold in both 163 | // directions and be unambiguous. More specifically: 164 | // 165 | // * An LIns can appear at most once in 'active'. 166 | // 167 | // * An LIns named by 'active[R]' must have an in-use 168 | // reservation that names R. 169 | // 170 | // * And vice versa: an LIns with an in-use reservation that 171 | // names R must be named by 'active[R]'. 172 | // 173 | // * If an LIns's reservation names 'deprecated_UnknownReg' then LIns 174 | // should not be in 'active'. 175 | // 176 | LIns* active[LastRegNum + 1]; // active[REGNUM(r)] = LIns that defines r 177 | int32_t usepri[LastRegNum + 1]; // used priority. lower = more likely to spill. 178 | RegisterMask free; // Registers currently free. 179 | RegisterMask managed; // Registers under management (invariant). 180 | int32_t priority; 181 | 182 | DECLARE_PLATFORM_REGALLOC() 183 | }; 184 | 185 | // Return the lowest numbered Register in mask. 186 | inline Register lsReg(RegisterMask mask) { 187 | // This is faster than it looks; we rely on the C++ optimizer 188 | // to strip the dead branch and inline just one alternative. 189 | Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) }; 190 | return r; 191 | } 192 | 193 | // Return the highest numbered Register in mask. 194 | inline Register msReg(RegisterMask mask) { 195 | // This is faster than it looks; we rely on the C++ optimizer 196 | // to strip the dead branch and inline just one alternative. 197 | Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) }; 198 | return r; 199 | } 200 | 201 | // Clear bit r in mask, then return lsReg(mask). 202 | inline Register nextLsReg(RegisterMask& mask, Register r) { 203 | return lsReg(mask &= ~rmask(r)); 204 | } 205 | 206 | // Clear bit r in mask, then return msReg(mask). 207 | inline Register nextMsReg(RegisterMask& mask, Register r) { 208 | return msReg(mask &= ~rmask(r)); 209 | } 210 | } 211 | #endif // __nanojit_RegAlloc__ 212 | -------------------------------------------------------------------------------- /nanojit/VMPI.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 (the 7 | * "License"); you may not use this file except in compliance with the License. You may obtain 8 | * a copy of the License at http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 11 | * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 12 | * language governing rights and limitations under the License. 13 | * 14 | * The Original Code is [Open Source Virtual Machine.] 15 | * 16 | * The Initial Developer of the Original Code is Adobe System Incorporated. Portions created 17 | * by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights 18 | * Reserved. 19 | * 20 | * Contributor(s): Adobe AS3 Team 21 | * Andreas Gal 22 | * 23 | * Alternatively, the contents of this file may be used under the terms of either the GNU 24 | * General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public 25 | * License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the 26 | * LGPL are applicable instead of those above. If you wish to allow use of your version of this 27 | * file only under the terms of either the GPL or the LGPL, and not to allow others to use your 28 | * version of this file under the terms of the MPL, indicate your decision by deleting provisions 29 | * above and replace them with the notice and other provisions required by the GPL or the 30 | * LGPL. If you do not delete the provisions above, a recipient may use your version of this file 31 | * under the terms of any one of the MPL, the GPL or the LGPL. 32 | * 33 | ***** END LICENSE BLOCK ***** */ 34 | 35 | #include "nanojit.h" 36 | 37 | #ifdef SOLARIS 38 | typedef caddr_t maddr_ptr; 39 | #else 40 | typedef void *maddr_ptr; 41 | #endif 42 | 43 | using namespace avmplus; 44 | 45 | size_t 46 | VMPI_getVMPageSize() 47 | { 48 | return 4096; 49 | } 50 | 51 | #ifdef WIN32 52 | void 53 | VMPI_setPageProtection(void *address, 54 | size_t size, 55 | bool executableFlag, 56 | bool writeableFlag) 57 | { 58 | DWORD oldProtectFlags = 0; 59 | DWORD newProtectFlags = 0; 60 | if ( executableFlag && writeableFlag ) { 61 | newProtectFlags = PAGE_EXECUTE_READWRITE; 62 | } else if ( executableFlag ) { 63 | newProtectFlags = PAGE_EXECUTE_READ; 64 | } else if ( writeableFlag ) { 65 | newProtectFlags = PAGE_READWRITE; 66 | } else { 67 | newProtectFlags = PAGE_READONLY; 68 | } 69 | 70 | BOOL retval; 71 | MEMORY_BASIC_INFORMATION mbi; 72 | do { 73 | VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); 74 | size_t markSize = size > mbi.RegionSize ? mbi.RegionSize : size; 75 | 76 | retval = VirtualProtect(address, markSize, newProtectFlags, &oldProtectFlags); 77 | NanoAssert(retval); 78 | 79 | address = (char*) address + markSize; 80 | size -= markSize; 81 | } while(size > 0 && retval); 82 | 83 | // We should not be clobbering PAGE_GUARD protections 84 | NanoAssert((oldProtectFlags & PAGE_GUARD) == 0); 85 | } 86 | 87 | #elif defined(AVMPLUS_OS2) 88 | 89 | void 90 | VMPI_setPageProtection(void *address, 91 | size_t size, 92 | bool executableFlag, 93 | bool writeableFlag) 94 | { 95 | ULONG flags = PAG_READ; 96 | if (executableFlag) { 97 | flags |= PAG_EXECUTE; 98 | } 99 | if (writeableFlag) { 100 | flags |= PAG_WRITE; 101 | } 102 | address = (void*)((size_t)address & ~(0xfff)); 103 | size = (size + 0xfff) & ~(0xfff); 104 | 105 | ULONG attribFlags = PAG_FREE; 106 | while (size) { 107 | ULONG attrib; 108 | ULONG range = size; 109 | ULONG retval = DosQueryMem(address, &range, &attrib); 110 | NanoAssert(retval == 0); 111 | 112 | // exit if this is the start of the next memory object 113 | if (attrib & attribFlags) { 114 | break; 115 | } 116 | attribFlags |= PAG_BASE; 117 | 118 | range = size > range ? range : size; 119 | retval = DosSetMem(address, range, flags); 120 | NanoAssert(retval == 0); 121 | 122 | address = (char*)address + range; 123 | size -= range; 124 | } 125 | } 126 | 127 | #else // !WIN32 && !AVMPLUS_OS2 128 | 129 | void VMPI_setPageProtection(void *address, 130 | size_t size, 131 | bool executableFlag, 132 | bool writeableFlag) 133 | { 134 | int bitmask = sysconf(_SC_PAGESIZE) - 1; 135 | // mprotect requires that the addresses be aligned on page boundaries 136 | void *endAddress = (void*) ((char*)address + size); 137 | void *beginPage = (void*) ((size_t)address & ~bitmask); 138 | void *endPage = (void*) (((size_t)endAddress + bitmask) & ~bitmask); 139 | size_t sizePaged = (size_t)endPage - (size_t)beginPage; 140 | 141 | int flags = PROT_READ; 142 | if (executableFlag) { 143 | flags |= PROT_EXEC; 144 | } 145 | if (writeableFlag) { 146 | flags |= PROT_WRITE; 147 | } 148 | int retval = mprotect((maddr_ptr)beginPage, (unsigned int)sizePaged, flags); 149 | NanoAssert(retval == 0); 150 | (void)retval; 151 | } 152 | 153 | #endif // WIN32 154 | -------------------------------------------------------------------------------- /nanojit/VMPI.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * Stub VMPI implementation to support standalone nanojit repository. 42 | * 43 | * Really only works if you *don't* have a busted-up C library. 44 | */ 45 | 46 | #ifndef __VMPI_h__ 47 | #define __VMPI_h__ 48 | 49 | #if defined(HAVE_CONFIG_H) && defined(NANOJIT_CENTRAL) 50 | #include "config.h" 51 | #endif 52 | 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #if defined(AVMPLUS_UNIX) || defined(AVMPLUS_OS2) 62 | #include 63 | #include 64 | #endif 65 | 66 | #ifdef AVMPLUS_WIN32 67 | #if ! defined(_STDINT_H) 68 | typedef signed char int8_t; 69 | typedef signed short int16_t; 70 | typedef signed int int32_t; 71 | typedef signed __int64 int64_t; 72 | typedef unsigned char uint8_t; 73 | typedef unsigned short uint16_t; 74 | typedef unsigned int uint32_t; 75 | typedef unsigned __int64 uint64_t; 76 | #endif 77 | #else 78 | #include 79 | #include 80 | #endif 81 | 82 | #define VMPI_strlen strlen 83 | #define VMPI_strcat strcat 84 | #define VMPI_strcmp strcmp 85 | #define VMPI_strncat strncat 86 | #define VMPI_strcpy strcpy 87 | #define VMPI_sprintf sprintf 88 | #ifdef _MSC_VER 89 | # define VMPI_snprintf sprintf_s 90 | #else 91 | # define VMPI_snprintf snprintf 92 | #endif 93 | #define VMPI_vfprintf vfprintf 94 | #define VMPI_memset memset 95 | #define VMPI_isdigit isdigit 96 | #define VMPI_getDate() 97 | 98 | extern size_t VMPI_getVMPageSize(); 99 | 100 | extern void VMPI_setPageProtection(void *address, 101 | size_t size, 102 | bool executableFlag, 103 | bool writeableFlag); 104 | 105 | // Keep this warning-set relatively in sync with platform/win32/win32-platform.h in tamarin. 106 | 107 | #ifdef _MSC_VER 108 | #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union 109 | #pragma warning(disable:4512) // assignment operator could not be generated 110 | #pragma warning(disable:4511) // can't generate copy ctor 111 | #pragma warning(disable:4127) // conditional expression is constant - appears to be compiler noise primarily 112 | #pragma warning(disable:4611) // interaction between _setjmp and destruct 113 | #pragma warning(disable:4725) // instruction may be inaccurate on some Pentiums 114 | #pragma warning(disable:4611) // interaction between '_setjmp' and C++ object destruction is non-portable 115 | #pragma warning(disable:4251) // X needs to have dll-interface to be used by clients of class Y 116 | 117 | // enable some that are off even in /W4 mode, but are still handy 118 | #pragma warning(default:4265) // 'class' : class has virtual functions, but destructor is not virtual 119 | #pragma warning(default:4905) // wide string literal cast to 'LPSTR' 120 | #pragma warning(default:4906) // string literal cast to 'LPWSTR' 121 | #pragma warning(default:4263) // 'function' : member function does not override any base class virtual member function 122 | #pragma warning(default:4264) // 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden 123 | #pragma warning(default:4266) // 'function' : no override available for virtual member function from base 'type'; function is hidden 124 | #pragma warning(default:4242) // 'identifier' : conversion from 'type1' to 'type2', possible loss of data 125 | #pragma warning(default:4263) // member function does not override any base class virtual member function 126 | #pragma warning(default:4296) // expression is always true (false) (Generally, an unsigned variable was used in a comparison operation with zero.) 127 | #endif 128 | 129 | // This part defined in avmshell.h but similarly required for a warning-free nanojit experience. 130 | #ifdef _MSC_VER 131 | #pragma warning(disable:4996) // 'scanf' was declared deprecated 132 | #endif 133 | 134 | // This part is inhibited manually by the CFLAGS in the tamarin configury. 135 | #ifdef _MSC_VER 136 | #pragma warning(disable:4291) // presence of a 'new' operator in nanojit/Allocator.h without matching 'delete' 137 | #endif 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /nanojit/avmplus.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 (the 7 | * "License"); you may not use this file except in compliance with the License. You may obtain 8 | * a copy of the License at http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 11 | * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 12 | * language governing rights and limitations under the License. 13 | * 14 | * The Original Code is [Open Source Virtual Machine.] 15 | * 16 | * The Initial Developer of the Original Code is Adobe System Incorporated. Portions created 17 | * by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights 18 | * Reserved. 19 | * 20 | * Contributor(s): Adobe AS3 Team 21 | * Andreas Gal 22 | * 23 | * Alternatively, the contents of this file may be used under the terms of either the GNU 24 | * General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public 25 | * License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the 26 | * LGPL are applicable instead of those above. If you wish to allow use of your version of this 27 | * file only under the terms of either the GPL or the LGPL, and not to allow others to use your 28 | * version of this file under the terms of the MPL, indicate your decision by deleting provisions 29 | * above and replace them with the notice and other provisions required by the GPL or the 30 | * LGPL. If you do not delete the provisions above, a recipient may use your version of this file 31 | * under the terms of any one of the MPL, the GPL or the LGPL. 32 | * 33 | ***** END LICENSE BLOCK ***** */ 34 | 35 | #include 36 | #include "nanojit.h" 37 | 38 | #ifdef SOLARIS 39 | typedef caddr_t maddr_ptr; 40 | #else 41 | typedef void *maddr_ptr; 42 | #endif 43 | 44 | using namespace avmplus; 45 | 46 | nanojit::Config AvmCore::config; 47 | 48 | void 49 | avmplus::AvmLog(char const *msg, ...) { 50 | va_list ap; 51 | va_start(ap, msg); 52 | VMPI_vfprintf(stderr, msg, ap); 53 | va_end(ap); 54 | } 55 | 56 | #ifdef _DEBUG 57 | namespace avmplus { 58 | void AvmAssertFail(const char* /* msg */) { 59 | fflush(stderr); 60 | #if defined(WIN32) 61 | DebugBreak(); 62 | exit(3); 63 | #elif defined(__APPLE__) 64 | /* 65 | * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are 66 | * trapped. 67 | */ 68 | *((int *) NULL) = 0; /* To continue from here in GDB: "return" then "continue". */ 69 | raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */ 70 | #else 71 | raise(SIGABRT); /* To continue from here in GDB: "signal 0". */ 72 | #endif 73 | } 74 | } 75 | #endif 76 | 77 | #ifdef WINCE 78 | 79 | // Due to the per-process heap slots on Windows Mobile, we can often run in to OOM 80 | // situations. jemalloc has worked around this problem, and so we use it here. 81 | // Using posix_memalign (or other malloc)functions) here only works because the OS 82 | // and hardware doesn't check for the execute bit being set. 83 | 84 | #ifndef MOZ_MEMORY 85 | #error MOZ_MEMORY required for building on WINCE 86 | #endif 87 | 88 | void* 89 | nanojit::CodeAlloc::allocCodeChunk(size_t nbytes) { 90 | void * buffer; 91 | posix_memalign(&buffer, 4096, nbytes); 92 | VMPI_setPageProtection(buffer, nbytes, true /* exec */, true /* write */); 93 | return buffer; 94 | } 95 | 96 | void 97 | nanojit::CodeAlloc::freeCodeChunk(void *p, size_t nbytes) { 98 | VMPI_setPageProtection(p, nbytes, false /* exec */, true /* write */); 99 | ::free(p); 100 | } 101 | 102 | #elif defined(WIN32) 103 | 104 | void* 105 | nanojit::CodeAlloc::allocCodeChunk(size_t nbytes) { 106 | return VirtualAlloc(NULL, 107 | nbytes, 108 | MEM_COMMIT | MEM_RESERVE, 109 | PAGE_EXECUTE_READWRITE); 110 | } 111 | 112 | void 113 | nanojit::CodeAlloc::freeCodeChunk(void *p, size_t) { 114 | VirtualFree(p, 0, MEM_RELEASE); 115 | } 116 | 117 | #elif defined(AVMPLUS_OS2) 118 | 119 | void* 120 | nanojit::CodeAlloc::allocCodeChunk(size_t nbytes) { 121 | 122 | // alloc from high memory, fallback to low memory if that fails 123 | void * addr; 124 | if (DosAllocMem(&addr, nbytes, OBJ_ANY | 125 | PAG_COMMIT | PAG_READ | PAG_WRITE | PAG_EXECUTE)) { 126 | if (DosAllocMem(&addr, nbytes, 127 | PAG_COMMIT | PAG_READ | PAG_WRITE | PAG_EXECUTE)) { 128 | return 0; 129 | } 130 | } 131 | return addr; 132 | } 133 | 134 | void 135 | nanojit::CodeAlloc::freeCodeChunk(void *p, size_t nbytes) { 136 | DosFreeMem(p); 137 | } 138 | 139 | #elif defined(AVMPLUS_UNIX) 140 | 141 | void* 142 | nanojit::CodeAlloc::allocCodeChunk(size_t nbytes) { 143 | return mmap(NULL, 144 | nbytes, 145 | PROT_READ | PROT_WRITE | PROT_EXEC, 146 | MAP_PRIVATE | MAP_ANON, 147 | -1, 148 | 0); 149 | } 150 | 151 | void 152 | nanojit::CodeAlloc::freeCodeChunk(void *p, size_t nbytes) { 153 | munmap((maddr_ptr)p, nbytes); 154 | } 155 | 156 | #else // !WIN32 && !AVMPLUS_OS2 && !AVMPLUS_UNIX 157 | 158 | void* 159 | nanojit::CodeAlloc::allocCodeChunk(size_t nbytes) { 160 | void* mem = valloc(nbytes); 161 | VMPI_setPageProtection(mem, nbytes, true /* exec */, true /* write */); 162 | return mem; 163 | } 164 | 165 | void 166 | nanojit::CodeAlloc::freeCodeChunk(void *p, size_t nbytes) { 167 | VMPI_setPageProtection(p, nbytes, false /* exec */, true /* write */); 168 | ::free(p); 169 | } 170 | 171 | #endif // WIN32 172 | 173 | // All of the allocCodeChunk/freeCodeChunk implementations above allocate 174 | // code memory as RWX and then free it, so the explicit page protection api's 175 | // below are no-ops. 176 | 177 | void 178 | nanojit::CodeAlloc::markCodeChunkWrite(void*, size_t) 179 | {} 180 | 181 | void 182 | nanojit::CodeAlloc::markCodeChunkExec(void*, size_t) 183 | {} 184 | 185 | -------------------------------------------------------------------------------- /nanojit/avmplus.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 (the 7 | * "License"); you may not use this file except in compliance with the License. You may obtain 8 | * a copy of the License at http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 11 | * WARRANTY OF ANY KIND, either express or implied. See the License for the specific 12 | * language governing rights and limitations under the License. 13 | * 14 | * The Original Code is [Open Source Virtual Machine.] 15 | * 16 | * The Initial Developer of the Original Code is Adobe System Incorporated. Portions created 17 | * by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights 18 | * Reserved. 19 | * 20 | * Contributor(s): Adobe AS3 Team 21 | * Andreas Gal 22 | * Asko Tontti 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of either the GNU 25 | * General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public 26 | * License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the 27 | * LGPL are applicable instead of those above. If you wish to allow use of your version of this 28 | * file only under the terms of either the GPL or the LGPL, and not to allow others to use your 29 | * version of this file under the terms of the MPL, indicate your decision by deleting provisions 30 | * above and replace them with the notice and other provisions required by the GPL or the 31 | * LGPL. If you do not delete the provisions above, a recipient may use your version of this file 32 | * under the terms of any one of the MPL, the GPL or the LGPL. 33 | * 34 | ***** END LICENSE BLOCK ***** */ 35 | 36 | #ifndef avm_h___ 37 | #define avm_h___ 38 | 39 | #include "VMPI.h" 40 | #include "njcpudetect.h" 41 | #include "njconfig.h" 42 | 43 | #if !defined(AVMPLUS_LITTLE_ENDIAN) && !defined(AVMPLUS_BIG_ENDIAN) 44 | #ifdef IS_BIG_ENDIAN 45 | #define AVMPLUS_BIG_ENDIAN 46 | #else 47 | #define AVMPLUS_LITTLE_ENDIAN 48 | #endif 49 | #endif 50 | 51 | #if defined(_MSC_VER) && defined(_M_IX86) 52 | #define FASTCALL __fastcall 53 | #elif defined(__GNUC__) && defined(__i386__) && \ 54 | ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) 55 | #define FASTCALL __attribute__((fastcall)) 56 | #else 57 | #define FASTCALL 58 | #define NO_FASTCALL 59 | #endif 60 | 61 | #if defined(NO_FASTCALL) 62 | #if defined(AVMPLUS_IA32) 63 | #define SIMULATE_FASTCALL(lr, state_ptr, frag_ptr, func_addr) \ 64 | asm volatile( \ 65 | "call *%%esi" \ 66 | : "=a" (lr) \ 67 | : "c" (state_ptr), "d" (frag_ptr), "S" (func_addr) \ 68 | : "memory", "cc" \ 69 | ); 70 | #endif /* defined(AVMPLUS_IA32) */ 71 | #endif /* defined(NO_FASTCALL) */ 72 | 73 | #ifdef WIN32 74 | #include 75 | #elif defined(AVMPLUS_OS2) 76 | #define INCL_DOSMEMMGR 77 | #include 78 | #endif 79 | 80 | #if defined(__SUNPRO_CC) 81 | #define __asm__ asm 82 | #define __volatile__ volatile 83 | #define __inline__ inline 84 | #endif 85 | 86 | #if defined(DEBUG) || defined(NJ_NO_VARIADIC_MACROS) 87 | #if !defined _DEBUG 88 | #define _DEBUG 89 | #endif 90 | #define NJ_VERBOSE 1 91 | #include 92 | #endif 93 | 94 | #ifdef _DEBUG 95 | namespace avmplus { 96 | void AvmAssertFail(const char* msg); 97 | } 98 | #endif 99 | 100 | #if defined(AVMPLUS_IA32) 101 | #if defined(_MSC_VER) 102 | 103 | # define AVMPLUS_HAS_RDTSC 1 104 | 105 | __declspec(naked) static inline __int64 rdtsc() 106 | { 107 | __asm 108 | { 109 | rdtsc; 110 | ret; 111 | } 112 | } 113 | 114 | #elif defined(__i386__) || defined(__i386) 115 | 116 | # define AVMPLUS_HAS_RDTSC 1 117 | 118 | static __inline__ unsigned long long rdtsc(void) 119 | { 120 | unsigned long long int x; 121 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); 122 | return x; 123 | } 124 | 125 | #endif /* compilers */ 126 | 127 | #elif defined(__x86_64__) 128 | 129 | # define AVMPLUS_HAS_RDTSC 1 130 | 131 | static __inline__ uint64_t rdtsc(void) 132 | { 133 | unsigned hi, lo; 134 | __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 135 | return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); 136 | } 137 | 138 | #elif defined(_MSC_VER) && defined(_M_AMD64) 139 | 140 | # define AVMPLUS_HAS_RDTSC 1 141 | 142 | #include 143 | #pragma intrinsic(__rdtsc) 144 | 145 | static inline unsigned __int64 rdtsc(void) 146 | { 147 | return __rdtsc(); 148 | } 149 | 150 | #elif defined(__powerpc__) 151 | 152 | # define AVMPLUS_HAS_RDTSC 1 153 | 154 | typedef unsigned long long int unsigned long long; 155 | 156 | static __inline__ unsigned long long rdtsc(void) 157 | { 158 | unsigned long long int result=0; 159 | unsigned long int upper, lower,tmp; 160 | __asm__ volatile( 161 | "0: \n" 162 | "\tmftbu %0 \n" 163 | "\tmftb %1 \n" 164 | "\tmftbu %2 \n" 165 | "\tcmpw %2,%0 \n" 166 | "\tbne 0b \n" 167 | : "=r"(upper),"=r"(lower),"=r"(tmp) 168 | ); 169 | result = upper; 170 | result = result<<32; 171 | result = result|lower; 172 | 173 | return(result); 174 | } 175 | 176 | #endif /* architecture */ 177 | 178 | #ifndef AVMPLUS_HAS_RDTSC 179 | # define AVMPLUS_HAS_RDTSC 0 180 | #endif 181 | 182 | struct JSContext; 183 | 184 | #ifdef PERFM 185 | # define PERFM_NVPROF(n,v) _nvprof(n,v) 186 | # define PERFM_NTPROF(n) _ntprof(n) 187 | # define PERFM_TPROF_END() _tprof_end() 188 | #else 189 | # define PERFM_NVPROF(n,v) 190 | # define PERFM_NTPROF(n) 191 | # define PERFM_TPROF_END() 192 | #endif 193 | 194 | namespace avmplus { 195 | 196 | typedef int FunctionID; 197 | 198 | extern void AvmLog(char const *msg, ...); 199 | 200 | static const int kstrconst_emptyString = 0; 201 | 202 | class AvmInterpreter 203 | { 204 | class Labels { 205 | public: 206 | const char* format(const void* ip) 207 | { 208 | static char buf[33]; 209 | sprintf(buf, "%p", ip); 210 | return buf; 211 | } 212 | }; 213 | 214 | Labels _labels; 215 | public: 216 | Labels* labels; 217 | 218 | AvmInterpreter() 219 | { 220 | labels = &_labels; 221 | } 222 | 223 | }; 224 | 225 | class AvmConsole 226 | { 227 | public: 228 | AvmConsole& operator<<(const char* s) 229 | { 230 | fprintf(stdout, "%s", s); 231 | return *this; 232 | } 233 | }; 234 | 235 | class AvmCore 236 | { 237 | public: 238 | AvmInterpreter interp; 239 | AvmConsole console; 240 | 241 | static nanojit::Config config; 242 | 243 | #ifdef AVMPLUS_IA32 244 | static inline bool 245 | use_sse2() 246 | { 247 | return config.i386_sse2; 248 | } 249 | #endif 250 | 251 | static inline bool 252 | use_cmov() 253 | { 254 | #ifdef AVMPLUS_IA32 255 | return config.i386_use_cmov; 256 | #else 257 | return true; 258 | #endif 259 | } 260 | }; 261 | 262 | /** 263 | * Bit vectors are an efficent method of keeping True/False information 264 | * on a set of items or conditions. Class BitSet provides functions 265 | * to manipulate individual bits in the vector. 266 | * 267 | * This object is not optimized for a fixed sized bit vector 268 | * it instead allows for dynamically growing the bit vector. 269 | */ 270 | class BitSet 271 | { 272 | public: 273 | enum { kUnit = 8*sizeof(long), 274 | kDefaultCapacity = 4 }; 275 | 276 | BitSet() 277 | { 278 | capacity = kDefaultCapacity; 279 | ar = (long*)calloc(capacity, sizeof(long)); 280 | reset(); 281 | } 282 | 283 | ~BitSet() 284 | { 285 | free(ar); 286 | } 287 | 288 | void reset() 289 | { 290 | for (int i = 0; i < capacity; i++) 291 | ar[i] = 0; 292 | } 293 | 294 | void set(int bitNbr) 295 | { 296 | int index = bitNbr / kUnit; 297 | int bit = bitNbr % kUnit; 298 | if (index >= capacity) 299 | grow(index+1); 300 | 301 | ar[index] |= (1<= 5 && NJ_COMPILER_ARM_ARCH <= 7); 102 | 103 | arm_arch = NJ_COMPILER_ARM_ARCH; 104 | arm_vfp = (arm_arch >= 7); 105 | 106 | #if defined(DEBUG) || defined(_DEBUG) 107 | arm_show_stats = true; 108 | #else 109 | arm_show_stats = false; 110 | #endif 111 | 112 | soft_float = !arm_vfp; 113 | 114 | #endif // NANOJIT_ARM 115 | } 116 | } 117 | #endif /* FEATURE_NANOJIT */ 118 | -------------------------------------------------------------------------------- /nanojit/njconfig.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef __njconfig_h__ 41 | #define __njconfig_h__ 42 | 43 | #include "avmplus.h" 44 | 45 | // Do not include nanojit.h here; this file should be usable without it. 46 | 47 | #ifdef FEATURE_NANOJIT 48 | 49 | namespace nanojit 50 | { 51 | /*** 52 | * A struct used to configure the assumptions that Assembler can make when 53 | * generating code. The ctor will fill in all fields with the most reasonable 54 | * values it can derive from compiler flags and/or runtime detection, but 55 | * the embedder is free to override any or all of them as it sees fit. 56 | * Using the ctor-provided default setup is guaranteed to provide a safe 57 | * runtime environment (though perhaps suboptimal in some cases), so an embedder 58 | * should replace these values with great care. 59 | * 60 | * Note that although many fields are used on only specific architecture(s), 61 | * this struct is deliberately declared without ifdef's for them, so (say) ARM-specific 62 | * fields are declared everywhere. This reduces build dependencies (so that this 63 | * files does not require nanojit.h to be included beforehand) and also reduces 64 | * clutter in this file; the extra storage space required is trivial since most 65 | * fields are single bits. 66 | */ 67 | struct Config 68 | { 69 | public: 70 | // fills in reasonable default values for all fields. 71 | Config(); 72 | 73 | // ARM architecture to assume when generate instructions for (currently, 4 <= arm_arch <= 7) 74 | uint8_t arm_arch; 75 | 76 | // If true, use CSE. 77 | uint32_t cseopt:1; 78 | 79 | // Can we use SSE2 instructions? (x86-only) 80 | uint32_t i386_sse2:1; 81 | 82 | // Can we use cmov instructions? (x86-only) 83 | uint32_t i386_use_cmov:1; 84 | 85 | // Should we use a virtual stack pointer? (x86-only) 86 | uint32_t i386_fixed_esp:1; 87 | 88 | // Whether or not to generate VFP instructions. (ARM only) 89 | uint32_t arm_vfp:1; 90 | 91 | // @todo, document me 92 | uint32_t arm_show_stats:1; 93 | 94 | // If true, use softfloat for all floating point operations, 95 | // whether or not an FPU is present. (ARM only for now, but might also includes MIPS in the future) 96 | uint32_t soft_float:1; 97 | 98 | // If true, compiler will insert a random amount of space in between functions (x86-32 only) 99 | uint32_t harden_function_alignment:1; 100 | 101 | // If true, compiler will insert randomly choosen no-op instructions at random locations within a compiled method (x86-32 only) 102 | uint32_t harden_nop_insertion:1; 103 | }; 104 | } 105 | 106 | #endif // FEATURE_NANOJIT 107 | #endif // __njconfig_h__ 108 | -------------------------------------------------------------------------------- /nanojit/njcpudetect.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ 2 | /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ 3 | /* ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is [Open Source Virtual Machine]. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Adobe System Incorporated. 20 | * Portions created by the Initial Developer are Copyright (C) 2004-2007 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * Adobe AS3 Team 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either the GNU General Public License Version 2 or later (the "GPL"), or 28 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef __njcpudetect__ 41 | #define __njcpudetect__ 42 | 43 | /*** 44 | * Note: this file should not include *any* other files, nor should it wrap 45 | * itself in ifdef FEATURE_NANOJIT, nor should it do anything other than 46 | * define preprocessor symbols. 47 | */ 48 | 49 | /*** 50 | * NJ_COMPILER_ARM_ARCH attempts to specify the minimum ARM architecture 51 | * that the C++ compiler has specified. Note that although Config::arm_arch 52 | * is initialized to this value by default, there is no requirement that they 53 | * be in sync. 54 | * 55 | * Note, this is done via #define so that downstream preprocessor usage can 56 | * examine it, but please don't attempt to redefine it. 57 | * 58 | * Note, this is deliberately not encased in "ifdef NANOJIT_ARM", as this file 59 | * may be included before that is defined. On non-ARM platforms we will hit the 60 | * "Unable to determine" case. 61 | */ 62 | 63 | // GCC and RealView usually define __ARM_ARCH__ 64 | #if defined(__ARM_ARCH__) 65 | 66 | #define NJ_COMPILER_ARM_ARCH __ARM_ARCH__ 67 | 68 | // ok, try well-known GCC flags ( see http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html ) 69 | #elif defined(__ARM_ARCH_7__) || \ 70 | defined(__ARM_ARCH_7A__) || \ 71 | defined(__ARM_ARCH_7M__) || \ 72 | defined(__ARM_ARCH_7R__) || \ 73 | defined(_ARM_ARCH_7) 74 | 75 | #define NJ_COMPILER_ARM_ARCH 7 76 | 77 | #elif defined(__ARM_ARCH_6__) || \ 78 | defined(__ARM_ARCH_6J__) || \ 79 | defined(__ARM_ARCH_6T2__) || \ 80 | defined(__ARM_ARCH_6Z__) || \ 81 | defined(__ARM_ARCH_6ZK__) || \ 82 | defined(__ARM_ARCH_6M__) || \ 83 | defined(_ARM_ARCH_6) 84 | 85 | #define NJ_COMPILER_ARM_ARCH 6 86 | 87 | #elif defined(__ARM_ARCH_5__) || \ 88 | defined(__ARM_ARCH_5T__) || \ 89 | defined(__ARM_ARCH_5E__) || \ 90 | defined(__ARM_ARCH_5TE__) 91 | 92 | #define NJ_COMPILER_ARM_ARCH 5 93 | 94 | #elif defined(__ARM_ARCH_4T__) 95 | 96 | #define NJ_COMPILER_ARM_ARCH 4 97 | 98 | // Visual C has its own mojo 99 | #elif defined(_MSC_VER) && defined(_M_ARM) 100 | 101 | #define NJ_COMPILER_ARM_ARCH _M_ARM 102 | 103 | // RVCT 104 | #elif defined(__TARGET_ARCH_ARM) 105 | 106 | #define NJ_COMPILER_ARM_ARCH __TARGET_ARCH_ARM 107 | 108 | #else 109 | 110 | // non-numeric value 111 | #define NJ_COMPILER_ARM_ARCH "Unable to determine valid NJ_COMPILER_ARM_ARCH (nanojit only supports ARMv4T or later)" 112 | 113 | #endif 114 | 115 | #endif // __njcpudetect__ 116 | -------------------------------------------------------------------------------- /vprof/manifest.mk: -------------------------------------------------------------------------------- 1 | # ***** BEGIN LICENSE BLOCK ***** 2 | # Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | # 4 | # The contents of this file are subject to the Mozilla Public License Version 5 | # 1.1 (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # http://www.mozilla.org/MPL/ 8 | # 9 | # Software distributed under the License is distributed on an "AS IS" basis, 10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | # for the specific language governing rights and limitations under the 12 | # License. 13 | # 14 | # The Original Code is [Open Source Virtual Machine]. 15 | # 16 | # The Initial Developer of the Original Code is 17 | # Intel Corporation. 18 | # Portions created by the Initial Developer are Copyright (C) 2008 19 | # the Initial Developer. All Rights Reserved. 20 | # 21 | # Contributor(s): 22 | # 23 | # Alternatively, the contents of this file may be used under the terms of 24 | # either the GNU General Public License Version 2 or later (the "GPL"), or 25 | # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 26 | # in which case the provisions of the GPL or the LGPL are applicable instead 27 | # of those above. If you wish to allow use of your version of this file only 28 | # under the terms of either the GPL or the LGPL, and not to allow others to 29 | # use your version of this file under the terms of the MPL, indicate your 30 | # decision by deleting the provisions above and replace them with the notice 31 | # and other provisions required by the GPL or the LGPL. If you do not delete 32 | # the provisions above, a recipient may use your version of this file under 33 | # the terms of any one of the MPL, the GPL or the LGPL. 34 | # 35 | # ***** END LICENSE BLOCK ***** 36 | 37 | avmplus_CXXSRCS := $(avmplus_CXXSRCS) \ 38 | $(curdir)/vprof.cpp \ 39 | $(NULL) 40 | -------------------------------------------------------------------------------- /vprof/readme.txt: -------------------------------------------------------------------------------- 1 | # ***** BEGIN LICENSE BLOCK ***** 2 | # Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | # 4 | # The contents of this file are subject to the Mozilla Public License Version 5 | # 1.1 (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # http:#www.mozilla.org/MPL/ 8 | # 9 | # Software distributed under the License is distributed on an "AS IS" basis, 10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | # for the specific language governing rights and limitations under the 12 | # License. 13 | # 14 | # The Original Code is [Open Source Virtual Machine.]. 15 | # 16 | # The Initial Developer of the Original Code is 17 | # Adobe System Incorporated. 18 | # Portions created by the Initial Developer are Copyright (C) 2008 19 | # the Initial Developer. All Rights Reserved. 20 | # 21 | # Contributor(s): 22 | # Adobe AS3 Team 23 | # 24 | # Alternatively, the contents of this file may be used under the terms of 25 | # either the GNU General Public License Version 2 or later (the "GPL"), or 26 | # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | # in which case the provisions of the GPL or the LGPL are applicable instead 28 | # of those above. If you wish to allow use of your version of this file only 29 | # under the terms of either the GPL or the LGPL, and not to allow others to 30 | # use your version of this file under the terms of the MPL, indicate your 31 | # decision by deleting the provisions above and replace them with the notice 32 | # and other provisions required by the GPL or the LGPL. If you do not delete 33 | # the provisions above, a recipient may use your version of this file under 34 | # the terms of any one of the MPL, the GPL or the LGPL. 35 | # 36 | # ***** END LICENSE BLOCK ***** 37 | 38 | The two files vprof.h and vprof.cpp implement a simple value-profiling mechanism. By including these two files in avmplus (or any other project), you can value profile data as you wish (currently integers). 39 | 40 | Usage: 41 | #include "vprof.h" // in the source file you want to use it 42 | 43 | _vprof (value); 44 | 45 | At the end of the execution, for each probe you'll get the data associated with the probe, such as: 46 | 47 | File line avg [min : max] total count 48 | ..\..\pcre\pcre_valid_utf8.cpp 182 50222.75916 [0 : 104947] 4036955604 80381 49 | 50 | The probe is defined at line 182 of file pcre_vali_utf8.cpp. It was called 80381 times. The min value of the probe was 0 while its max was 10497 and its average was 50222.75916. The total sum of all values of the probe is 4036955604. Later, I plan to add more options on the spectrum of data among others. 51 | 52 | A few typical uses 53 | ------------------ 54 | 55 | To see how many times a given function gets executed do: 56 | 57 | void f() 58 | { 59 | _vprof(1); 60 | ... 61 | } 62 | 63 | void f() 64 | { 65 | _vprof(1); 66 | ... 67 | if (...) { 68 | _vprof(1); 69 | ... 70 | } else { 71 | _vprof(1); 72 | ... 73 | } 74 | } 75 | 76 | Here are a few examples of using the value-profiling utility: 77 | 78 | _vprof (e); 79 | at the end of program execution, you'll get a dump of the source location of this probe, 80 | its min, max, average, the total sum of all instances of e, and the total number of times this probe was called. 81 | 82 | _vprof (x > 0); 83 | shows how many times and what percentage of the cases x was > 0, 84 | that is the probablitiy that x > 0. 85 | 86 | _vprof (n % 2 == 0); 87 | shows how many times n was an even number 88 | as well as th probablitiy of n being an even number. 89 | 90 | _hprof (n, 4, 1000, 5000, 5001, 10000); 91 | gives you the histogram of n over the given 4 bucket boundaries: 92 | # cases < 1000 93 | # cases >= 1000 and < 5000 94 | # cases >= 5000 and < 5001 95 | # cases >= 5001 and < 10000 96 | # cases >= 10000 97 | 98 | _nvprof ("event name", value); 99 | all instances with the same name are merged 100 | so, you can call _vprof with the same event name at difference places 101 | 102 | _vprof (e, myProbe); 103 | value profile e and call myProbe (void* vprofID) at the profiling point. 104 | inside the probe, the client has the predefined variables: 105 | _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers 106 | _IVAR1, ..., IVAR4 general integer registrs 107 | _I64VAR1, ..., I64VAR4 general integer64 registrs 108 | _DVAR1, ..., _DVAR4 general double registers 109 | _GENPTR a generic pointer that can be used by the client 110 | the number of registers can be changed in vprof.h 111 | 112 | Named Events 113 | ------------ 114 | _nvprof ("event name", value); 115 | all instances with the same name are merged 116 | so, you can call _vprof with the same event name at difference places 117 | 118 | 119 | Custom Probes 120 | -------------- 121 | You can call your own custom probe at the profiling point. 122 | _vprof (v, myProbe); 123 | value profile v and call myProbe (void* vprofID) at the profiling point 124 | inside the probe, the client has the predefined variables: 125 | _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers 126 | _IVAR1, ..., IVAR4 general integer registrs 127 | _I64VAR1, ..., I64VAR4 general integer64 registrs 128 | _DVAR1, ..., _DVAR4 general double registers 129 | the number of registers can be changed in vprof.h 130 | _GENPTR a generic pointer that can be used for almost anything 131 | -------------------------------------------------------------------------------- /vprof/testVprofMT.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Value-Profiling Utility. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Intel Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 2008 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Mohammad R. Haghighat [mohammad.r.haghighat@intel.com] 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "vprof.h" 44 | 45 | static void cProbe (void* vprofID) 46 | { 47 | if (_VAL == _IVAR1) _I64VAR1 ++; 48 | _IVAR1 = _IVAR0; 49 | 50 | if (_VAL == _IVAR0) _I64VAR0 ++; 51 | _IVAR0 = (int) _VAL; 52 | 53 | _DVAR0 = ((double)_I64VAR0) / _COUNT; 54 | _DVAR1 = ((double)_I64VAR1) / _COUNT; 55 | } 56 | 57 | //__declspec (thread) boolean cv; 58 | //#define if(c) cv = (c); _vprof (cv); if (cv) 59 | //#define if(c) cv = (c); _vprof (cv, cProbe); if (cv) 60 | 61 | #define THREADS 1 62 | #define COUNT 100000 63 | #define SLEEPTIME 0 64 | 65 | static int64_t evens = 0; 66 | static int64_t odds = 0; 67 | 68 | void sub(int val) 69 | { 70 | int i; 71 | //_vprof (1); 72 | for (i = 0; i < COUNT; i++) { 73 | //_nvprof ("Iteration", 1); 74 | //_nvprof ("Iteration", 1); 75 | _vprof (i); 76 | //_vprof (i); 77 | //_hprof(i, 3, (int64_t) 1000, (int64_t)2000, (int64_t)3000); 78 | //_hprof(i, 3, 10000, 10001, 3000000); 79 | //_nhprof("Event", i, 3, 10000, 10001, 3000000); 80 | //_nhprof("Event", i, 3, 10000, 10001, 3000000); 81 | //Sleep(SLEEPTIME); 82 | if (i % 2 == 0) { 83 | //_vprof (i); 84 | ////_hprof(i, 3, 10000, 10001, 3000000); 85 | //_nvprof ("Iteration", i); 86 | evens ++; 87 | } else { 88 | //_vprof (1); 89 | _vprof (i, cProbe); 90 | odds ++; 91 | } 92 | //_nvprof ("Iterate", 1); 93 | } 94 | //printf("sub %d done.\n", val); 95 | } 96 | 97 | HANDLE array[THREADS]; 98 | 99 | static int run (void) 100 | { 101 | int i; 102 | 103 | time_t start_time = time(0); 104 | 105 | for (i = 0; i < THREADS; i++) { 106 | array[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)sub, (LPVOID)i, 0, 0); 107 | } 108 | 109 | for (i = 0; i < THREADS; i++) { 110 | WaitForSingleObject(array[i], INFINITE); 111 | } 112 | 113 | return 0; 114 | } 115 | 116 | int main () 117 | { 118 | DWORD start, end; 119 | 120 | start = GetTickCount (); 121 | run (); 122 | end = GetTickCount (); 123 | 124 | printf ("\nRun took %d msecs\n\n", end-start); 125 | } 126 | -------------------------------------------------------------------------------- /vprof/vprof.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Value-Profiling Utility. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Intel Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 2008 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Mohammad R. Haghighat [mohammad.r.haghighat@intel.com] 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #include "VMPI.h" 40 | 41 | // Note, this is not supported in configurations with more than one AvmCore running 42 | // in the same process. 43 | 44 | #ifdef WIN32 45 | #include "windows.h" 46 | #else 47 | #define __cdecl 48 | #include 49 | #include 50 | #endif 51 | 52 | #include "vprof.h" 53 | 54 | #define MIN(x,y) ((x) <= (y) ? x : y) 55 | #define MAX(x,y) ((x) >= (y) ? x : y) 56 | 57 | #ifndef MAXINT 58 | #define MAXINT int(unsigned(-1)>>1) 59 | #endif 60 | 61 | #ifndef MAXINT64 62 | #define MAXINT64 int64_t(uint64_t(-1)>>1) 63 | #endif 64 | 65 | #ifndef __STDC_WANT_SECURE_LIB__ 66 | #define sprintf_s(b,size,fmt,...) sprintf((b),(fmt),__VA_ARGS__) 67 | #endif 68 | 69 | #if THREADED 70 | #define DO_LOCK(lock) Lock(lock); { 71 | #define DO_UNLOCK(lock) }; Unlock(lock) 72 | #else 73 | #define DO_LOCK(lock) { (void)(lock); 74 | #define DO_UNLOCK(lock) } 75 | #endif 76 | 77 | #if THREAD_SAFE 78 | #define LOCK(lock) DO_LOCK(lock) 79 | #define UNLOCK(lock) DO_UNLOCK(lock) 80 | #else 81 | #define LOCK(lock) { (void)(lock); 82 | #define UNLOCK(lock) } 83 | #endif 84 | 85 | static entry* entries = NULL; 86 | static bool notInitialized = true; 87 | static long glock = LOCK_IS_FREE; 88 | 89 | #define Lock(lock) while (_InterlockedCompareExchange(lock, LOCK_IS_TAKEN, LOCK_IS_FREE) == LOCK_IS_TAKEN){}; 90 | #define Unlock(lock) _InterlockedCompareExchange(lock, LOCK_IS_FREE, LOCK_IS_TAKEN); 91 | 92 | #if defined(WIN32) && !defined(UNDER_CE) 93 | static void vprof_printf(const char* format, ...) 94 | { 95 | va_list args; 96 | va_start(args, format); 97 | 98 | char buf[1024]; 99 | vsnprintf(buf, sizeof(buf), format, args); 100 | 101 | va_end(args); 102 | 103 | printf(buf); 104 | ::OutputDebugStringA(buf); 105 | } 106 | #else 107 | #define vprof_printf printf 108 | #endif 109 | 110 | inline static entry* reverse (entry* s) 111 | { 112 | entry_t e, n, p; 113 | 114 | p = NULL; 115 | for (e = s; e; e = n) { 116 | n = e->next; 117 | e->next = p; 118 | p = e; 119 | } 120 | 121 | return p; 122 | } 123 | 124 | static char* f (double d) 125 | { 126 | static char s[80]; 127 | char* p; 128 | sprintf_s (s, sizeof(s), "%lf", d); 129 | p = s+VMPI_strlen(s)-1; 130 | while (*p == '0') { 131 | *p = '\0'; 132 | p--; 133 | if (p == s) break; 134 | } 135 | if (*p == '.') *p = '\0'; 136 | return s; 137 | } 138 | 139 | static void dumpProfile (void) 140 | { 141 | entry_t e; 142 | 143 | entries = reverse(entries); 144 | vprof_printf ("event avg [min : max] total count\n"); 145 | for (e = entries; e; e = e->next) { 146 | if (e->count == 0) continue; // ignore entries with zero count. 147 | vprof_printf ("%s", e->file); 148 | if (e->line >= 0) { 149 | vprof_printf (":%d", e->line); 150 | } 151 | vprof_printf (" %s [%lld : %lld] %lld %lld ", 152 | f(((double)e->sum)/((double)e->count)), (long long int)e->min, (long long int)e->max, (long long int)e->sum, (long long int)e->count); 153 | if (e->h) { 154 | int j = MAXINT; 155 | for (j = 0; j < e->h->nbins; j ++) { 156 | vprof_printf ("(%lld < %lld) ", (long long int)e->h->count[j], (long long int)e->h->lb[j]); 157 | } 158 | vprof_printf ("(%lld >= %lld) ", (long long int)e->h->count[e->h->nbins], (long long int)e->h->lb[e->h->nbins-1]); 159 | } 160 | if (e->func) { 161 | int j; 162 | for (j = 0; j < NUM_EVARS; j++) { 163 | if (e->ivar[j] != 0) { 164 | vprof_printf ("IVAR%d %d ", j, e->ivar[j]); 165 | } 166 | } 167 | for (j = 0; j < NUM_EVARS; j++) { 168 | if (e->i64var[j] != 0) { 169 | vprof_printf ("I64VAR%d %lld ", j, (long long int)e->i64var[j]); 170 | } 171 | } 172 | for (j = 0; j < NUM_EVARS; j++) { 173 | if (e->dvar[j] != 0) { 174 | vprof_printf ("DVAR%d %lf ", j, e->dvar[j]); 175 | } 176 | } 177 | } 178 | vprof_printf ("\n"); 179 | } 180 | entries = reverse(entries); 181 | } 182 | 183 | inline static entry_t findEntry (char* file, int line) 184 | { 185 | for (entry_t e = entries; e; e = e->next) { 186 | if ((e->line == line) && (VMPI_strcmp (e->file, file) == 0)) { 187 | return e; 188 | } 189 | } 190 | return NULL; 191 | } 192 | 193 | // Initialize the location pointed to by 'id' to a new value profile entry 194 | // associated with 'file' and 'line', or do nothing if already initialized. 195 | // An optional final argument provides a user-defined probe function. 196 | 197 | int initValueProfile(void** id, char* file, int line, ...) 198 | { 199 | DO_LOCK (&glock); 200 | entry_t e = (entry_t) *id; 201 | if (notInitialized) { 202 | atexit (dumpProfile); 203 | notInitialized = false; 204 | } 205 | 206 | if (e == NULL) { 207 | e = findEntry (file, line); 208 | if (e) { 209 | *id = e; 210 | } 211 | } 212 | 213 | if (e == NULL) { 214 | va_list va; 215 | e = (entry_t) malloc (sizeof(entry)); 216 | e->lock = LOCK_IS_FREE; 217 | e->file = file; 218 | e->line = line; 219 | e->value = 0; 220 | e->sum = 0; 221 | e->count = 0; 222 | e->min = 0; 223 | e->max = 0; 224 | // optional probe function argument 225 | va_start (va, line); 226 | e->func = (void (__cdecl*)(void*)) va_arg (va, void*); 227 | va_end (va); 228 | e->h = NULL; 229 | e->genptr = NULL; 230 | VMPI_memset (&e->ivar, 0, sizeof(e->ivar)); 231 | VMPI_memset (&e->i64var, 0, sizeof(e->i64var)); 232 | VMPI_memset (&e->dvar, 0, sizeof(e->dvar)); 233 | e->next = entries; 234 | entries = e; 235 | *id = e; 236 | } 237 | DO_UNLOCK (&glock); 238 | 239 | return 0; 240 | } 241 | 242 | // Record a value profile event. 243 | 244 | int profileValue(void* id, int64_t value) 245 | { 246 | entry_t e = (entry_t) id; 247 | long* lock = &(e->lock); 248 | LOCK (lock); 249 | e->value = value; 250 | if (e->count == 0) { 251 | e->sum = value; 252 | e->count = 1; 253 | e->min = value; 254 | e->max = value; 255 | } else { 256 | e->sum += value; 257 | e->count ++; 258 | e->min = MIN (e->min, value); 259 | e->max = MAX (e->max, value); 260 | } 261 | if (e->func) e->func (e); 262 | UNLOCK (lock); 263 | 264 | return 0; 265 | } 266 | 267 | // Initialize the location pointed to by 'id' to a new histogram profile entry 268 | // associated with 'file' and 'line', or do nothing if already initialized. 269 | 270 | int initHistProfile(void** id, char* file, int line, int nbins, ...) 271 | { 272 | DO_LOCK (&glock); 273 | entry_t e = (entry_t) *id; 274 | if (notInitialized) { 275 | atexit (dumpProfile); 276 | notInitialized = false; 277 | } 278 | 279 | if (e == NULL) { 280 | e = findEntry (file, line); 281 | if (e) { 282 | *id = e; 283 | } 284 | } 285 | 286 | if (e == NULL) { 287 | va_list va; 288 | hist_t h; 289 | int b, n, s; 290 | int64_t* lb; 291 | 292 | e = (entry_t) malloc (sizeof(entry)); 293 | e->lock = LOCK_IS_FREE; 294 | e->file = file; 295 | e->line = line; 296 | e->value = 0; 297 | e->sum = 0; 298 | e->count = 0; 299 | e->min = 0; 300 | e->max = 0; 301 | e->func = NULL; 302 | e->h = h = (hist_t) malloc (sizeof(hist)); 303 | n = 1+MAX(nbins,0); 304 | h->nbins = n-1; 305 | s = n*sizeof(int64_t); 306 | lb = (int64_t*) malloc (s); 307 | h->lb = lb; 308 | VMPI_memset (h->lb, 0, s); 309 | h->count = (int64_t*) malloc (s); 310 | VMPI_memset (h->count, 0, s); 311 | 312 | va_start (va, nbins); 313 | for (b = 0; b < nbins; b++) { 314 | //lb[b] = va_arg (va, int64_t); 315 | lb[b] = va_arg (va, int); 316 | } 317 | lb[b] = MAXINT64; 318 | va_end (va); 319 | 320 | e->genptr = NULL; 321 | VMPI_memset (&e->ivar, 0, sizeof(e->ivar)); 322 | VMPI_memset (&e->i64var, 0, sizeof(e->i64var)); 323 | VMPI_memset (&e->dvar, 0, sizeof(e->dvar)); 324 | e->next = entries; 325 | entries = e; 326 | *id = e; 327 | } 328 | DO_UNLOCK (&glock); 329 | 330 | return 0; 331 | } 332 | 333 | // Record a histogram profile event. 334 | 335 | int histValue(void* id, int64_t value) 336 | { 337 | entry_t e = (entry_t) id; 338 | long* lock = &(e->lock); 339 | hist_t h = e->h; 340 | int nbins = h->nbins; 341 | int64_t* lb = h->lb; 342 | int b; 343 | 344 | LOCK (lock); 345 | e->value = value; 346 | if (e->count == 0) { 347 | e->sum = value; 348 | e->count = 1; 349 | e->min = value; 350 | e->max = value; 351 | } else { 352 | e->sum += value; 353 | e->count ++; 354 | e->min = MIN (e->min, value); 355 | e->max = MAX (e->max, value); 356 | } 357 | for (b = 0; b < nbins; b ++) { 358 | if (value < lb[b]) break; 359 | } 360 | h->count[b] ++; 361 | UNLOCK (lock); 362 | 363 | return 0; 364 | } 365 | 366 | #if defined(_MSC_VER) && defined(_M_IX86) 367 | uint64_t readTimestampCounter() 368 | { 369 | // read the cpu cycle counter. 1 tick = 1 cycle on IA32 370 | _asm rdtsc; 371 | } 372 | #elif defined(__GNUC__) && (__i386__ || __x86_64__) 373 | uint64_t readTimestampCounter() 374 | { 375 | uint32_t lo, hi; 376 | __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 377 | return (uint64_t(hi) << 32) | lo; 378 | } 379 | #else 380 | // add stub for platforms without it, so fat builds don't fail 381 | uint64_t readTimestampCounter() { return 0; } 382 | #endif 383 | 384 | -------------------------------------------------------------------------------- /vprof/vprof.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Value-Profiling Utility. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Intel Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 2008 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * Mohammad R. Haghighat [mohammad.r.haghighat@intel.com] 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either the GNU General Public License Version 2 or later (the "GPL"), or 27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | // 40 | // Here are a few examples of using the value-profiling utility: 41 | // 42 | // _vprof (e); 43 | // at the end of program execution, you'll get a dump of the source location of this probe, 44 | // its min, max, average, the total sum of all instances of e, and the total number of times this probe was called. 45 | // 46 | // _vprof (x > 0); 47 | // shows how many times and what percentage of the cases x was > 0, 48 | // that is the probablitiy that x > 0. 49 | // 50 | // _vprof (n % 2 == 0); 51 | // shows how many times n was an even number 52 | // as well as th probablitiy of n being an even number. 53 | // 54 | // _hprof (n, 4, 1000, 5000, 5001, 10000); 55 | // gives you the histogram of n over the given 4 bucket boundaries: 56 | // # cases < 1000 57 | // # cases >= 1000 and < 5000 58 | // # cases >= 5000 and < 5001 59 | // # cases >= 5001 and < 10000 60 | // # cases >= 10000 61 | // 62 | // _nvprof ("event name", value); 63 | // all instances with the same name are merged 64 | // so, you can call _vprof with the same event name at difference places 65 | // 66 | // _vprof (e, myProbe); 67 | // value profile e and call myProbe (void* vprofID) at the profiling point. 68 | // inside the probe, the client has the predefined variables: 69 | // _VAL, _COUNT, _SUM, _MIN, _MAX, and the general purpose registers 70 | // _IVAR1, ..., IVAR4 general integer registrs 71 | // _I64VAR1, ..., I64VAR4 general integer64 registrs 72 | // _DVAR1, ..., _DVAR4 general double registers 73 | // _GENPTR a generic pointer that can be used by the client 74 | // the number of registers can be changed in vprof.h 75 | // 76 | 77 | #ifndef __VPROF__ 78 | #define __VPROF__ 79 | // 80 | // If the application for which you want to use vprof is threaded, THREADED must be defined as 1, otherwise define it as 0 81 | // 82 | // If your application is not threaded, define THREAD_SAFE 0, 83 | // otherwise, you have the option of setting THREAD_SAFE to 1 which results in exact counts or to 0 which results in a much more efficient but non-exact counts 84 | // 85 | #define THREADED 0 86 | #define THREAD_SAFE 0 87 | 88 | #include "VMPI.h" 89 | 90 | // Note, this is not supported in configurations with more than one AvmCore running 91 | // in the same process. 92 | 93 | // portable align macro 94 | #if defined(_MSC_VER) 95 | #define vprof_align8(t) __declspec(align(8)) t 96 | #elif defined(__GNUC__) 97 | #define vprof_align8(t) t __attribute__ ((aligned (8))) 98 | #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) 99 | #define vprof_align8(t) t __attribute__ ((aligned (8))) 100 | #elif defined(VMCFG_SYMBIAN) 101 | #define vprof_align8(t) t __attribute__ ((aligned (8))) 102 | #endif 103 | 104 | #ifdef __cplusplus 105 | extern "C" { 106 | #endif 107 | 108 | int initValueProfile(void** id, char* file, int line, ...); 109 | int profileValue(void* id, int64_t value); 110 | int initHistProfile(void** id, char* file, int line, int nbins, ...); 111 | int histValue(void* id, int64_t value); 112 | uint64_t readTimestampCounter(); 113 | 114 | #ifdef __cplusplus 115 | } 116 | #endif 117 | 118 | //#define DOPROF 119 | 120 | #ifndef DOPROF 121 | #define _nvprof(e,v) 122 | #ifndef VMCFG_SYMBIAN 123 | #define _vprof(v,...) 124 | #define _hprof(v,n,...) 125 | #define _nhprof(e,v,n,...) 126 | #define _ntprof_begin(e) 127 | #define _ntprof_end(e) 128 | #define _jvprof_init(id,...) 129 | #define _jnvprof_init(id,e,...) 130 | #define _jhprof_init(id,n,...) 131 | #define _jnhprof_init(id,e,n,...) 132 | #define _jvprof(id,v) 133 | #define _jhprof(id,v) 134 | #endif // ! VMCFG_SYMBIAN 135 | #else 136 | 137 | // Historical/compatibility note: 138 | // The macros below were originally written using conditional expressions, not if/else. The original author 139 | // said that this was done to allow _vprof and _nvprof to be used in an expression context, but the old code 140 | // had already wrapped the macro bodies in { }, so it is not clear how this could have worked. At present, 141 | // the profiling macros must appear in a statement context only. 142 | 143 | #define _vprof(v,...) \ 144 | do { \ 145 | static void* id = 0; \ 146 | if (id == 0) \ 147 | initValueProfile(&id, __FILE__, __LINE__, ##__VA_ARGS__, NULL); \ 148 | profileValue(id, (int64_t) (v)); \ 149 | } while (0) 150 | 151 | #define _nvprof(e,v) \ 152 | do { \ 153 | static void* id = 0; \ 154 | if (id == 0) \ 155 | initValueProfile(&id, (char*) (e), -1, NULL); \ 156 | profileValue(id, (int64_t) (v)); \ 157 | } while (0) 158 | 159 | #define _hprof(v,n,...) \ 160 | do { \ 161 | static void* id = 0; \ 162 | if (id == 0) \ 163 | initHistProfile(&id, __FILE__, __LINE__, (int) (n), ##__VA_ARGS__); \ 164 | histValue(id, (int64_t) (v)); \ 165 | } while (0) 166 | 167 | #define _nhprof(e,v,n,...) \ 168 | do { \ 169 | static void* id = 0; \ 170 | if (id == 0) \ 171 | initHistProfile(&id, (char*) (e), -1, (int) (n), ##__VA_ARGS__); \ 172 | histValue(id, (int64_t) (v)); \ 173 | } while (0) 174 | 175 | // Profile execution time between _ntprof_begin(e) and _ntprof_end(e). 176 | // The tag 'e' must match at the beginning and end of the region to 177 | // be timed. Regions may be nested or overlap arbitrarily, as it is 178 | // the tag alone that defines the begin/end correspondence. 179 | 180 | #define _ntprof_begin(e) \ 181 | do { \ 182 | static void* id = 0; \ 183 | if (id == 0) \ 184 | initValueProfile(&id, (char*)(e), -1, NULL); \ 185 | ((entry_t)id)->i64var[0] = readTimestampCounter(); \ 186 | } while (0) 187 | 188 | // Assume 2.6 Ghz CPU 189 | #define TICKS_PER_USEC 2600 190 | 191 | #define _ntprof_end(e) \ 192 | do { \ 193 | static void* id = 0; \ 194 | uint64_t stop = readTimestampCounter(); \ 195 | if (id == 0) \ 196 | initValueProfile(&id, (char*)(e), -1, NULL); \ 197 | uint64_t start = ((entry_t)id)->i64var[0]; \ 198 | uint64_t usecs = (stop - start) / TICKS_PER_USEC; \ 199 | profileValue(id, usecs); \ 200 | } while (0) 201 | 202 | // These macros separate the creation of a profile record from its later usage. 203 | // They are intended for profiling JIT-generated code. Once created, the JIT can 204 | // bind a pointer to the profile record into the generated code, which can then 205 | // record profile events during execution. 206 | 207 | #define _jvprof_init(id,...) \ 208 | if (*(id) == 0) \ 209 | initValueProfile((id), __FILE__, __LINE__, ##__VA_ARGS__, NULL) 210 | 211 | #define _jnvprof_init(id,e,...) \ 212 | if (*(id) == 0) \ 213 | initValueProfile((id), (char*) (e), -1, ##__VA_ARGS__, NULL) 214 | 215 | #define _jhprof_init(id,n,...) \ 216 | if (*(id) == 0) \ 217 | initHistProfile((id), __FILE__, __LINE__, (int) (n), ##__VA_ARGS__) 218 | 219 | #define _jnhprof_init(id,e,n,...) \ 220 | if (*(id) == 0) \ 221 | initHistProfile((id), (char*) (e), -1, (int) (n), ##__VA_ARGS__) 222 | 223 | // Calls to the _jvprof and _jhprof macros must be wrapped in a non-inline 224 | // function in order to be invoked from JIT-compiled code. 225 | 226 | #define _jvprof(id,v) \ 227 | profileValue((id), (int64_t) (v)) 228 | 229 | #define _jhprof(id,v) \ 230 | histValue((id), (int64_t) (v)) 231 | 232 | #endif 233 | 234 | #define NUM_EVARS 4 235 | 236 | enum { 237 | LOCK_IS_FREE = 0, 238 | LOCK_IS_TAKEN = 1 239 | }; 240 | 241 | extern 242 | #ifdef __cplusplus 243 | "C" 244 | #endif 245 | long _InterlockedCompareExchange ( 246 | long volatile * Destination, 247 | long Exchange, 248 | long Comperand 249 | ); 250 | 251 | typedef struct hist hist; 252 | 253 | typedef struct hist { 254 | int nbins; 255 | int64_t* lb; 256 | int64_t* count; 257 | } *hist_t; 258 | 259 | typedef struct entry entry; 260 | 261 | typedef struct entry { 262 | long lock; 263 | char* file; 264 | int line; 265 | int64_t value; 266 | int64_t count; 267 | int64_t sum; 268 | int64_t min; 269 | int64_t max; 270 | void (*func)(void*); 271 | hist* h; 272 | 273 | entry* next; 274 | 275 | // exposed to the clients 276 | void* genptr; 277 | int ivar[NUM_EVARS]; 278 | vprof_align8(int64_t) i64var[NUM_EVARS]; 279 | vprof_align8(double) dvar[NUM_EVARS]; 280 | // 281 | 282 | char pad[128]; // avoid false sharing 283 | } *entry_t; 284 | 285 | #define _VAL ((entry_t)vprofID)->value 286 | #define _COUNT ((entry_t)vprofID)->count 287 | #define _SUM ((entry_t)vprofID)->sum 288 | #define _MIN ((entry_t)vprofID)->min 289 | #define _MAX ((entry_t)vprofID)->max 290 | 291 | #define _GENPTR ((entry_t)vprofID)->genptr 292 | 293 | #define _IVAR0 ((entry_t)vprofID)->ivar[0] 294 | #define _IVAR1 ((entry_t)vprofID)->ivar[1] 295 | #define _IVAR2 ((entry_t)vprofID)->ivar[2] 296 | #define _IVAR3 ((entry_t)vprofID)->ivar[3] 297 | 298 | #define _I64VAR0 ((entry_t)vprofID)->i64var[0] 299 | #define _I64VAR1 ((entry_t)vprofID)->i64var[1] 300 | #define _I64VAR2 ((entry_t)vprofID)->i64var[2] 301 | #define _I64VAR3 ((entry_t)vprofID)->i64var[3] 302 | 303 | #define _DVAR0 ((entry_t)vprofID)->dvar[0] 304 | #define _DVAR1 ((entry_t)vprofID)->dvar[1] 305 | #define _DVAR2 ((entry_t)vprofID)->dvar[2] 306 | #define _DVAR3 ((entry_t)vprofID)->dvar[3] 307 | 308 | #endif /* __VPROF__ */ 309 | --------------------------------------------------------------------------------