! lib1funcs.S for picoJava. ! Copyright (C) 2000, 2001 Free Software Foundation, Inc. ! ! This file is free software; you can redistribute it and/or modify it ! under the terms of the GNU General Public License as published by the ! Free Software Foundation; either version 2, or (at your option) any ! later version. ! ! In addition to the permissions in the GNU General Public License, the ! Free Software Foundation gives you unlimited permission to link the ! compiled version of this file into combinations with other programs, ! and to distribute those combinations without any restriction coming ! from the use of this file. (The General Public License restrictions ! do apply in other respects; for example, they cover modification of ! the file, and distribution when not linked into a combine ! executable.) ! ! This file is distributed in the hope that it will be useful, but ! WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with this program; see the file COPYING. If not, write to ! the Free Software Foundation, 59 Temple Place - Suite 330, ! Boston, MA 02111-1307, USA. ! #ifdef Lvhelper ! The vhelper copies unnamed args in a varargs function from the ! opstack onto the aggregate stack. It is a bit tricky since the ! opstack does not exist in real memory, so can not have its address taken, ! and since the opstack is being played with, there is nowhere to stick ! the temporaries. .globl __vhelper __vhelper: ! incoming ! vars-> named0 ! named1 ! ... ! unnamed0 ! unnamed1 ! ... ! pc ! vars ! #named ! return pc ! work out total size everything below the named args and ! allocate that space on the aggregate stack + 3 extra words ! for some temps. ! g0 = old g0 ! g0+4 = vars ! g0+8 = pc ! g0+12 = last unnamed arg ! .... write_global1 write_global2 ! tos = #named args provided by callee. ! move down the aggstack to make room for all the unnamed args ! and the 12 bytes of extra stuff we have to pay attention to. ! g0 = old_g0 - ((vars - optop) + named_bytes + 12) - stuff we just pushed ! build new global0 read_global0 read_vars read_optop isub ! tos = vars - optop (# bytes in all args) bipush 4 isub ! subtract out fudge for current stuff on stack. read_global2 isub ! subtract out # words named. isub dup dup ! store old global0 in new global0 spot. read_global0 swap store_word ! store new global0 value into global0 write_global0 ! work out address to stop copying, which is vars - #named args bytes ! but since we will have pushed stuff onto the stack when the comparison ! is made, adjust by the fudge factor. read_vars read_global2 bipush 12 iadd isub ! optop= finish, vars, pc, ... ! now pop off args from the opstack and copy to aggstack till all done. ! during the loop the opstack looks like ! (optop_finish_addr) (destination_addr) (named_n) (named_n-1) .... ! each iteration pops off one more element. again: dup_x2 read_optop if_icmpeq done iconst_4 iadd dup_x2 store_word goto again done: dup2_x1 ; pop2 ; pop !leave pointer on top. ! return to caller with varargs pointer as ! the next argument and the restoring global0 as the next. read_global0 ; load_word ! restore returning pc and vars read_global0 ; bipush 8; iadd; load_word read_global0 ; bipush 4; iadd; load_word ! return to caller. read_global1 write_pc #endif #ifdef __LITTLE_ENDIAN__ #define AL iload_1 #define AH iload_0 #define BL iload_3 #define BH iload_2 #else #define AL iload_0 #define AH iload_1 #define BL iload_2 #define BH iload_3 #endif #ifdef Lpjucmpdi2 ! like ucmpdi2, but returns <0,0,>0 depending on comparison input. ! and returns answer on the stack, not in global1. - much like an ! actual lucmp instruction would do if there was one. ! big little ! ! vars-> 0 a low high ! 1 a high low ! 2 b low high ! 3 b high low ! ! compares a to b ! a > b return 1 ! a = b return 0 ! a < b return -1 .globl __pjucmpdi2 __pjucmpdi2: ! first see if we can compare the numbers using ! the signed instruction. AH BH if_icmpne high_words_diff AL BL iucmp return1 ! and low word if high word is equal. high_words_diff: AH BH iucmp return1 #endif