1 /***************************** alpha/gen.c *************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Contains the codegenerator for an Alpha processor.
8 This module generates Alpha machine code for a sequence of
9 pseudo commands (PCMDs).
11 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
12 Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
14 Last Change: 1997/10/22
16 *******************************************************************************/
20 /*******************************************************************************
22 Datatypes and Register Allocations:
23 -----------------------------------
25 On 64-bit-machines (like the Alpha) all operands are stored in the
26 registers in a 64-bit form, even when the correspondig JavaVM
27 operands only need 32 bits.
28 This is done by a canonical representation:
30 32-bit integers are allways stored as sign-extended 64-bit values
31 (this approach is directly supported by the Alpha architecture and
32 is very easy to implement).
34 32-bit-floats are stored in a 64-bit doubleprecision register by
35 simply expanding the exponent and mantissa with zeroes.
36 (also supported by the architecture)
41 The calling conventions and the layout of the stack is
42 explained in detail in the documention file: calling.doc
44 *******************************************************************************/
47 /************************ Preallocated registers ******************************/
49 /* integer registers */
51 #define REG_RESULT 0 /* to deliver method results */
52 #define REG_EXCEPTION 1 /* to throw an exception across method bounds */
54 #define REG_RA 26 /* return address */
55 #define REG_PV 27 /* procedure vector, must be provided by caller */
56 #define REG_METHODPTR 28 /* pointer to the place from where the procedure */
57 /* vector has been fetched */
58 #define REG_ITMP1 25 /* temporary register */
59 #define REG_ITMP2 28 /* temporary register */
60 #define REG_ITMP3 29 /* temporary register */
62 #define REG_SP 30 /* stack pointer */
63 #define REG_ZERO 31 /* allways zero */
65 /* floating point registers */
67 #define REG_FRESULT 0 /* to deliver floating point method results */
68 #define REG_FTMP1 28 /* temporary floating point register */
69 #define REG_FTMP2 29 /* temporary floating point register */
70 #define REG_FTMP3 30 /* temporary floating point register */
73 /******************** register descripton - array *****************************/
75 /* #define REG_RES 0 reserved register for OS or code generator */
76 /* #define REG_RET 1 return value register */
77 /* #define REG_EXC 2 exception value register */
78 /* #define REG_SAV 3 (callee) saved register */
79 /* #define REG_TMP 4 scratch temporary register (caller saved) */
80 /* #define REG_ARG 5 argument register (caller saved) */
82 /* #define REG_END -1 last entry in tables */
85 REG_RET, REG_EXC, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
86 REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
87 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
88 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
91 #define INT_SAV_FST 9 /* first int callee saved register */
92 #define INT_SAV_CNT 7 /* number of int callee saved registers */
93 #define INT_ARG_FST 16 /* first int callee saved register */
94 #define INT_ARG_CNT 6 /* number of int callee saved registers */
96 /* for use of reserved registers, see comment above */
98 int regdescfloat[] = {
99 REG_RET, REG_TMP, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
100 REG_SAV, REG_SAV, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
101 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP,
102 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES,
105 #define FLT_SAV_FST 2 /* first int callee saved register */
106 #define FLT_SAV_CNT 8 /* number of int callee saved registers */
107 #define FLT_ARG_FST 16 /* first int callee saved register */
108 #define FLT_ARG_CNT 6 /* number of int callee saved registers */
110 /* for use of reserved registers, see comment above */
113 /*** parameter allocation mode ***/
115 int reg_parammode = PARAMMODE_NUMBERED;
117 /* parameter-registers will be allocated by assigning the
118 1. parameter: int/float-reg 16
119 2. parameter: int/float-reg 17
120 3. parameter: int/float-reg 18 ....
124 /************************** stackframe-infos **********************************/
126 int localvars_base; /* offset in stackframe for the local variables */
127 int savedregs_base; /* offset in stackframe for the save area */
128 int parentargs_base; /* offset in stackframe for the parameter from the caller*/
130 /* -> see file 'calling.doc' */
133 /******************** macros to create code ***********************************/
135 /* 3-address-operations: M_OP3
137 fu ..... function-number
138 a ..... register number source 1
139 b ..... register number or constant integer source 2
140 c ..... register number destination
141 const .. switch to use b as constant integer
142 (0 means: use b as register number)
143 (1 means: use b as constant 8-bit-integer)
145 #define M_OP3(op,fu,a,b,c,const) \
146 mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
147 ((const)<<12)|((fu)<<5)|((c)) )
149 /* 3-address-floating-point-operation: M_FOP3
151 fu .... function-number
152 a,b ... source floating-point registers
153 c ..... destination register
155 #define M_FOP3(op,fu,a,b,c) \
156 mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
158 /* branch instructions: M_BRA
160 a ...... register to be tested
161 disp ... relative address to be jumped to (divided by 4)
163 #define M_BRA(op,a,disp) \
164 mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
167 /* memory operations: M_MEM
169 a ...... source/target register for memory access
170 b ...... base register
171 disp ... displacement (16 bit signed) to be added to b
173 #define M_MEM(op,a,b,disp) \
174 mcode_adds4 ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
177 /***** macros for all used commands (see an Alpha-manual for description) *****/
179 #define M_LDA(a,b,disp) M_MEM (0x08,a,b,disp) /* low const */
180 #define M_LDAH(a,b,disp) M_MEM (0x09,a,b,disp) /* high const */
181 #define M_BLDU(a,b,disp) M_MEM (0x0a,a,b,disp) /* 8 load */
182 #define M_SLDU(a,b,disp) M_MEM (0x0c,a,b,disp) /* 16 load */
183 #define M_ILD(a,b,disp) M_MEM (0x28,a,b,disp) /* 32 load */
184 #define M_LLD(a,b,disp) M_MEM (0x29,a,b,disp) /* 64 load */
185 #define M_BST(a,b,disp) M_MEM (0x0e,a,b,disp) /* 8 store */
186 #define M_SST(a,b,disp) M_MEM (0x0d,a,b,disp) /* 16 store */
187 #define M_IST(a,b,disp) M_MEM (0x2c,a,b,disp) /* 32 store */
188 #define M_LST(a,b,disp) M_MEM (0x2d,a,b,disp) /* 64 store */
190 #define M_BSEXT(b,c) M_OP3 (0x1c,0x0,REG_ZERO,b,c,0) /* 8 signext */
191 #define M_SSEXT(b,c) M_OP3 (0x1c,0x1,REG_ZERO,b,c,0) /* 16 signext */
193 #define M_BR(disp) M_BRA (0x30,REG_ZERO,disp) /* branch */
194 #define M_BSR(ra,disp) M_BRA (0x34,ra,disp) /* branch sbr */
195 #define M_BEQZ(a,disp) M_BRA (0x39,a,disp) /* br a == 0 */
196 #define M_BLTZ(a,disp) M_BRA (0x3a,a,disp) /* br a < 0 */
197 #define M_BLEZ(a,disp) M_BRA (0x3b,a,disp) /* br a <= 0 */
198 #define M_BNEZ(a,disp) M_BRA (0x3d,a,disp) /* br a != 0 */
199 #define M_BGEZ(a,disp) M_BRA (0x3e,a,disp) /* br a >= 0 */
200 #define M_BGTZ(a,disp) M_BRA (0x3f,a,disp) /* br a > 0 */
202 #define M_JMP(a,b) M_MEM (0x1a,a,b,0x0000) /* jump */
203 #define M_JSR(a,b) M_MEM (0x1a,a,b,0x4000) /* call sbr */
204 #define M_RET(a,b) M_MEM (0x1a,a,b,0x8000) /* return */
206 #define M_IADD(a,b,c,const) M_OP3 (0x10,0x0, a,b,c,const) /* 32 add */
207 #define M_LADD(a,b,c,const) M_OP3 (0x10,0x20, a,b,c,const) /* 64 add */
208 #define M_ISUB(a,b,c,const) M_OP3 (0x10,0x09, a,b,c,const) /* 32 sub */
209 #define M_LSUB(a,b,c,const) M_OP3 (0x10,0x29, a,b,c,const) /* 64 sub */
210 #define M_IMUL(a,b,c,const) M_OP3 (0x13,0x00, a,b,c,const) /* 32 mul */
211 #define M_LMUL(a,b,c,const) M_OP3 (0x13,0x20, a,b,c,const) /* 64 mul */
213 #define M_CMPEQ(a,b,c,const) M_OP3 (0x10,0x2d, a,b,c,const) /* c = a == b */
214 #define M_CMPLT(a,b,c,const) M_OP3 (0x10,0x4d, a,b,c,const) /* c = a < b */
215 #define M_CMPLE(a,b,c,const) M_OP3 (0x10,0x6d, a,b,c,const) /* c = a <= b */
217 #define M_CMPULE(a,b,c,const) M_OP3 (0x10,0x3d, a,b,c,const) /* c = a <= b */
219 #define M_AND(a,b,c,const) M_OP3 (0x11,0x00, a,b,c,const) /* c = a & b */
220 #define M_OR(a,b,c,const) M_OP3 (0x11,0x20, a,b,c,const) /* c = a | b */
221 #define M_XOR(a,b,c,const) M_OP3 (0x11,0x40, a,b,c,const) /* c = a ^ b */
223 #define M_SLL(a,b,c,const) M_OP3 (0x12,0x39, a,b,c,const) /* c = a << b */
224 #define M_SRA(a,b,c,const) M_OP3 (0x12,0x3c, a,b,c,const) /* c = a >> b */
225 #define M_SRL(a,b,c,const) M_OP3 (0x12,0x34, a,b,c,const) /* c = a >>>b */
227 #define M_FLD(a,b,disp) M_MEM (0x22,a,b,disp) /* load flt */
228 #define M_DLD(a,b,disp) M_MEM (0x23,a,b,disp) /* load dbl */
229 #define M_FST(a,b,disp) M_MEM (0x26,a,b,disp) /* store flt */
230 #define M_DST(a,b,disp) M_MEM (0x27,a,b,disp) /* store dbl */
232 #define M_FADD(a,b,c) M_FOP3 (0x16, 0x080, a,b,c) /* flt add */
233 #define M_DADD(a,b,c) M_FOP3 (0x16, 0x0a0, a,b,c) /* dbl add */
234 #define M_FSUB(a,b,c) M_FOP3 (0x16, 0x081, a,b,c) /* flt sub */
235 #define M_DSUB(a,b,c) M_FOP3 (0x16, 0x0a1, a,b,c) /* dbl sub */
236 #define M_FMUL(a,b,c) M_FOP3 (0x16, 0x082, a,b,c) /* flt mul */
237 #define M_DMUL(a,b,c) M_FOP3 (0x16, 0x0a2, a,b,c) /* dbl mul */
238 #define M_FDIV(a,b,c) M_FOP3 (0x16, 0x083, a,b,c) /* flt div */
239 #define M_DDIV(a,b,c) M_FOP3 (0x16, 0x0a3, a,b,c) /* dbl div */
241 #define M_CVTLF(a,b,c) M_FOP3 (0x16, 0x0bc, a,b,c) /* long2flt */
242 #define M_CVTLD(a,b,c) M_FOP3 (0x16, 0x0be, a,b,c) /* long2dbl */
243 #define M_CVTDL(a,b,c) M_FOP3 (0x16, 0x0af, a,b,c) /* dbl2long */
244 #define M_CVTDL_C(a,b,c) M_FOP3 (0x16, 0x02f, a,b,c) /* dbl2long */
246 #define M_FCMPEQ(a,b,c) M_FOP3 (0x16, 0x0a5, a,b,c) /* c = a==b */
247 #define M_FCMPLT(a,b,c) M_FOP3 (0x16, 0x0a6, a,b,c) /* c = a<b */
249 #define M_FMOV(fa,fb) M_FOP3 (0x17, 0x020, fa,fa,fb) /* b = a */
250 #define M_FMOVN(fa,fb) M_FOP3 (0x17, 0x021, fa,fa,fb) /* b = -a */
252 #define M_FBEQZ(fa,disp) M_BRA (0x31,fa,disp) /* br a == 0.0*/
254 /****** macros for special commands (see an Alpha-manual for description) *****/
256 #define M_S4ADDL(a,b,c,const) M_OP3 (0x10,0x02, a,b,c,const) /* c = a*4 + b */
257 #define M_S4ADDQ(a,b,c,const) M_OP3 (0x10,0x22, a,b,c,const) /* c = a*4 + b */
258 #define M_S4SUBL(a,b,c,const) M_OP3 (0x10,0x0b, a,b,c,const) /* c = a*4 - b */
259 #define M_S4SUBQ(a,b,c,const) M_OP3 (0x10,0x2b, a,b,c,const) /* c = a*4 - b */
260 #define M_S8ADDL(a,b,c,const) M_OP3 (0x10,0x12, a,b,c,const) /* c = a*8 + b */
261 #define M_S8ADDQ(a,b,c,const) M_OP3 (0x10,0x32, a,b,c,const) /* c = a*8 + b */
262 #define M_S8SUBL(a,b,c,const) M_OP3 (0x10,0x1b, a,b,c,const) /* c = a*8 - b */
263 #define M_S8SUBQ(a,b,c,const) M_OP3 (0x10,0x3b, a,b,c,const) /* c = a*8 - b */
265 #define M_LLD_U(a,b,disp) M_MEM (0x0b,a,b,disp) /* unalign ld */
266 #define M_LST_U(a,b,disp) M_MEM (0x0f,a,b,disp) /* unalign st */
268 #define M_ZAP(a,b,c,const) M_OP3 (0x12,0x30, a,b,c,const)
269 #define M_ZAPNOT(a,b,c,const) M_OP3 (0x12,0x31, a,b,c,const)
270 #define M_EXTBL(a,b,c,const) M_OP3 (0x12,0x06, a,b,c,const)
271 #define M_EXTWL(a,b,c,const) M_OP3 (0x12,0x16, a,b,c,const)
272 #define M_EXTLL(a,b,c,const) M_OP3 (0x12,0x26, a,b,c,const)
273 #define M_EXTQL(a,b,c,const) M_OP3 (0x12,0x36, a,b,c,const)
274 #define M_EXTWH(a,b,c,const) M_OP3 (0x12,0x5a, a,b,c,const)
275 #define M_EXTLH(a,b,c,const) M_OP3 (0x12,0x6a, a,b,c,const)
276 #define M_EXTQH(a,b,c,const) M_OP3 (0x12,0x7a, a,b,c,const)
277 #define M_INSBL(a,b,c,const) M_OP3 (0x12,0x0b, a,b,c,const)
278 #define M_INSWL(a,b,c,const) M_OP3 (0x12,0x1b, a,b,c,const)
279 #define M_INSLL(a,b,c,const) M_OP3 (0x12,0x2b, a,b,c,const)
280 #define M_INSQL(a,b,c,const) M_OP3 (0x12,0x3b, a,b,c,const)
281 #define M_INSWH(a,b,c,const) M_OP3 (0x12,0x57, a,b,c,const)
282 #define M_INSLH(a,b,c,const) M_OP3 (0x12,0x67, a,b,c,const)
283 #define M_INSQH(a,b,c,const) M_OP3 (0x12,0x77, a,b,c,const)
284 #define M_MSKBL(a,b,c,const) M_OP3 (0x12,0x02, a,b,c,const)
285 #define M_MSKWL(a,b,c,const) M_OP3 (0x12,0x12, a,b,c,const)
286 #define M_MSKLL(a,b,c,const) M_OP3 (0x12,0x22, a,b,c,const)
287 #define M_MSKQL(a,b,c,const) M_OP3 (0x12,0x32, a,b,c,const)
288 #define M_MSKWH(a,b,c,const) M_OP3 (0x12,0x52, a,b,c,const)
289 #define M_MSKLH(a,b,c,const) M_OP3 (0x12,0x62, a,b,c,const)
290 #define M_MSKQH(a,b,c,const) M_OP3 (0x12,0x72, a,b,c,const)
293 /****** macros for unused commands (see an Alpha-manual for description) ******/
295 #define M_ANDNOT(a,b,c,const) M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b */
296 #define M_ORNOT(a,b,c,const) M_OP3 (0x11,0x28, a,b,c,const) /* c = a |~ b */
297 #define M_XORNOT(a,b,c,const) M_OP3 (0x11,0x48, a,b,c,const) /* c = a ^~ b */
299 #define M_CMOVEQ(a,b,c,const) M_OP3 (0x11,0x24, a,b,c,const) /* a==0 ? c=b */
300 #define M_CMOVNE(a,b,c,const) M_OP3 (0x11,0x26, a,b,c,const) /* a!=0 ? c=b */
301 #define M_CMOVLT(a,b,c,const) M_OP3 (0x11,0x44, a,b,c,const) /* a< 0 ? c=b */
302 #define M_CMOVGE(a,b,c,const) M_OP3 (0x11,0x46, a,b,c,const) /* a>=0 ? c=b */
303 #define M_CMOVLE(a,b,c,const) M_OP3 (0x11,0x64, a,b,c,const) /* a<=0 ? c=b */
304 #define M_CMOVGT(a,b,c,const) M_OP3 (0x11,0x66, a,b,c,const) /* a> 0 ? c=b */
306 #define M_CMPULT(a,b,c,const) M_OP3 (0x10,0x1d, a,b,c,const)
307 #define M_CMPBGE(a,b,c,const) M_OP3 (0x10,0x0f, a,b,c,const)
309 #define M_FCMPUN(a,b,c) M_FOP3 (0x16, 0x0a4, a,b,c) /* unordered */
310 #define M_FCMPLE(a,b,c) M_FOP3 (0x16, 0x0a7, a,b,c) /* c = a<=b */
312 #define M_FBNEZ(fa,disp) M_BRA (0x35,fa,disp)
313 #define M_FBLEZ(fa,disp) M_BRA (0x33,fa,disp)
315 #define M_JMP_CO(a,b) M_MEM (0x1a,a,b,0xc000) /* call cosub */
318 /******************** system independent macros *******************************/
322 /************** additional functions to generate code *************************/
326 generates an integer-move from register a to b.
327 if a and b are the same int-register, no code will be generated.
330 static void M_INTMOVE(int a, int b)
338 generates a floating-point-move from register a to b.
339 if a and b are the same float-register, no code will be generated
342 static void M_FLTMOVE(int a, int b)
350 this function generates code to fetch data from a pseudo-register
351 into a real register.
352 If the pseudo-register has actually been assigned to a real
353 register, no code will be emitted, since following operations
354 can use this register directly.
356 v: pseudoregister to be fetched from
357 tempregnum: temporary register to be used if v is actually spilled to ram
359 return: the register number, where the operand can be found after
360 fetching (this wil be either tempregnum or the register
361 number allready given to v)
364 static int var_to_reg_int (varid v, int tempregnum)
366 reginfo *ri = v->reg;
368 if (!(ri->typeflags & REG_INMEMORY))
373 M_LLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
378 static int var_to_reg_flt (varid v, int tempregnum)
380 reginfo *ri = v->reg;
383 if (!(ri->typeflags & REG_INMEMORY))
388 M_DLD (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
394 This function determines a register, to which the result of an
395 operation should go, when it is ultimatively intended to store the result
397 If v is assigned to an actual register, this register will be
399 Otherwise (when v is spilled) this function returns tempregnum.
402 static int reg_of_var(varid v, int tempregnum)
404 if (!(v->reg->typeflags & REG_INMEMORY))
410 /* store_reg_to_var_xxx:
411 This function generates the code to store the result of an operation
412 back into a spilled pseudo-variable.
413 If the pseudo-variable has not been spilled in the first place, this
414 function will generate nothing.
416 v ............ Pseudovariable
417 tempregnum ... Number of the temporary registers as returned by
421 static void store_reg_to_var_int (varid v, int tempregnum)
423 reginfo *ri = v->reg;
425 if (!(ri->typeflags & REG_INMEMORY))
430 M_LST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
433 static void store_reg_to_var_flt (varid v, int tempregnum)
435 reginfo *ri = v->reg;
437 if (!(ri->typeflags & REG_INMEMORY))
442 M_DST (tempregnum, REG_SP, 8 * (localvars_base + ri->num) );
446 /***************** functions to process the pseudo commands *******************/
449 function to generate method-call
452 static void gen_method (pcmd *c)
459 for (p = 0; p < c->u.method.paramnum; p++) {
460 ri = c->u.method.params[p]->reg;
462 if (p < INT_ARG_CNT) { /* arguments that go into registers */
463 if (IS_INT_LNG_REG(ri->typeflags)) {
464 if (!(ri->typeflags & REG_INMEMORY))
465 M_INTMOVE(ri->num, INT_ARG_FST+p);
467 M_LLD(INT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
470 if (!(ri->typeflags & REG_INMEMORY))
471 M_FLTMOVE (ri->num, FLT_ARG_FST+p);
473 M_DLD(FLT_ARG_FST+p, REG_SP, 8*(localvars_base + ri->num));
476 else { /* arguments that go into memory */
477 pa = p - INT_ARG_CNT;
478 if (pa >= arguments_num)
479 panic ("invalid stackframe structure");
481 if (IS_INT_LNG_REG(ri->typeflags)) {
482 r = var_to_reg_int (c->u.method.params[p], REG_ITMP1);
483 M_LST(r, REG_SP, 8 * (0 + pa));
486 r = var_to_reg_flt (c->u.method.params[p], REG_FTMP1);
487 M_DST (r, REG_SP, 8 * (0 + pa));
494 a = dseg_addaddress ( (void*) (c->u.method.builtin) );
496 M_LLD (REG_PV, REG_PV, a); /* Pointer to built-in-function */
499 case CMD_INVOKESTATIC:
500 case CMD_INVOKESPECIAL:
501 a = dseg_addaddress ( c->u.method.method->stubroutine );
503 M_LLD (REG_PV, REG_PV, a ); /* Method-Pointer in r27 */
507 case CMD_INVOKEVIRTUAL:
509 M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));
510 M_LLD (REG_PV, REG_METHODPTR,
511 OFFSET(vftbl,table[0]) +
512 sizeof(methodptr) * c->u.method.method->vftblindex );
516 case CMD_INVOKEINTERFACE:
517 ci = c->u.method.method->class;
519 M_LLD (REG_METHODPTR, 16, OFFSET(java_objectheader, vftbl));
520 M_LLD (REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl, interfacetable[0]) -
521 sizeof(methodptr*) * ci->index);
522 M_LLD (REG_PV, REG_METHODPTR, sizeof(methodptr) * (c->u.method.method - ci->methods) );
527 sprintf (logtext, "Unkown PCMD-Command: %d", c->opcode);
535 M_JSR (REG_RA, REG_PV);
536 if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
538 s4 ml=-mcodelen, mh=0;
539 while (ml<-32768) { ml+=65536; mh--; }
540 M_LDA (REG_PV, REG_RA, ml );
541 M_LDAH (REG_PV, REG_PV, mh );
547 if (IS_INT_LNG_REG(ri->typeflags)) {
548 if (!(ri->typeflags & REG_INMEMORY))
549 M_INTMOVE (REG_RESULT, ri->num);
550 else M_LST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
553 if (!(ri->typeflags & REG_INMEMORY))
554 M_FLTMOVE (REG_RESULT, ri->num);
555 else M_DST (REG_RESULT, REG_SP, 8 * (localvars_base + ri->num) );
559 if (c->u.method.exceptionvar) {
560 ri = c->u.method.exceptionvar->reg;
561 if (!(ri->typeflags & REG_INMEMORY))
562 M_INTMOVE (REG_EXCEPTION, ri->num);
563 else M_LST (REG_EXCEPTION, REG_SP, 8 *(localvars_base + ri->num) );
568 /************************ function block_genmcode ******************************
570 generates machine code for a complete basic block
572 *******************************************************************************/
575 static void block_genmcode(basicblock *b)
581 mcode_blockstart (b);
583 for(c = list_first(&(b->pcmdlist));
585 c = list_next(&(b->pcmdlist), c))
590 M_LDA (REG_SP, REG_SP, -8);
591 a = dseg_addaddress (c->u.a.value);
592 M_LLD(REG_ITMP1, REG_PV, a);
593 M_LST(REG_ITMP1, REG_SP, 0);
594 a = dseg_addaddress ((void*) (builtin_trace_args));
595 M_LLD(REG_PV, REG_PV, a);
596 M_JSR (REG_RA, REG_PV);
597 if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
599 s4 ml=-mcodelen, mh=0;
600 while (ml<-32768) { ml+=65536; mh--; }
601 M_LDA (REG_PV, REG_RA, ml );
602 M_LDAH (REG_PV, REG_PV, mh );
604 M_LDA (REG_SP, REG_SP, 8);
609 /*********************** constant operations **************************/
611 case CMD_LOADCONST_I:
612 d = reg_of_var(c->dest, REG_ITMP1);
613 if ( (c->u.i.value >= -32768) && (c->u.i.value <= 32767) ) {
614 M_LDA (d, REG_ZERO, c->u.i.value);
617 a = dseg_adds4 (c->u.i.value);
618 M_ILD (d, REG_PV, a);
620 store_reg_to_var_int(c->dest, d);
623 case CMD_LOADCONST_L:
624 d = reg_of_var(c->dest, REG_ITMP1);
626 if ((c->u.l.value >= -32768) && (c->u.l.value <= 32767) ) {
627 M_LDA (d, REG_ZERO, c->u.l.value);
630 a = dseg_adds8 (c->u.l.value);
631 M_LLD (d, REG_PV, a);
634 a = dseg_adds8 (c->u.l.value);
635 M_LLD (d, REG_PV, a);
637 store_reg_to_var_int(c->dest, d);
640 case CMD_LOADCONST_F:
641 d = reg_of_var (c->dest, REG_FTMP1);
642 a = dseg_addfloat (c->u.f.value);
643 M_FLD (d, REG_PV, a);
644 store_reg_to_var_flt (c->dest, d);
647 case CMD_LOADCONST_D:
648 d = reg_of_var (c->dest, REG_FTMP1);
649 a = dseg_adddouble (c->u.d.value);
650 M_DLD (d, REG_PV, a);
651 store_reg_to_var_flt (c->dest, d);
655 case CMD_LOADCONST_A:
656 d = reg_of_var(c->dest, REG_ITMP1);
658 a = dseg_addaddress (c->u.a.value);
659 M_LLD (d, REG_PV, a);
662 M_INTMOVE (REG_ZERO, d);
664 store_reg_to_var_int(c->dest, d);
667 /************************* move operation *****************************/
670 if (IS_INT_LNG_REG(c->source1->reg->typeflags)) {
671 d = reg_of_var(c->dest, REG_ITMP1);
672 s1 = var_to_reg_int(c->source1, d);
674 store_reg_to_var_int(c->dest, d);
677 d = reg_of_var(c->dest, REG_FTMP1);
678 s1 = var_to_reg_flt(c->source1, d);
680 store_reg_to_var_flt(c->dest, d);
685 /********************* integer operations *****************************/
688 s1 = var_to_reg_int(c->source1, REG_ITMP1);
689 d = reg_of_var(c->dest, REG_ITMP3);
690 if ((c->u.i.value >= 0) && (c->u.i.value <= 256)) {
691 M_IADD (s1, c->u.i.value, d, 1);
693 else if ((c->u.i.value >= -256) && (c->u.i.value < 0)) {
694 M_ISUB (s1, (-c->u.i.value), d, 1);
697 M_LDA (d, s1, c->u.i.value);
698 M_IADD (d, REG_ZERO, d, 0);
700 store_reg_to_var_int(c->dest, d);
704 s1 = var_to_reg_int(c->source1, REG_ITMP1);
705 d = reg_of_var(c->dest, REG_ITMP3);
706 M_ISUB (REG_ZERO, s1, d, 0);
707 store_reg_to_var_int(c->dest, d);
711 s1 = var_to_reg_int(c->source1, REG_ITMP1);
712 d = reg_of_var(c->dest, REG_ITMP3);
713 M_LSUB (REG_ZERO, s1, d, 0);
714 store_reg_to_var_int(c->dest, d);
718 s1 = var_to_reg_int(c->source1, REG_ITMP1);
719 d = reg_of_var(c->dest, REG_ITMP3);
721 store_reg_to_var_int(c->dest, d);
725 s1 = var_to_reg_int(c->source1, REG_ITMP1);
726 d = reg_of_var(c->dest, REG_ITMP3);
727 M_IADD (s1, REG_ZERO, d , 0);
728 store_reg_to_var_int(c->dest, d);
732 s1 = var_to_reg_int(c->source1, REG_ITMP1);
733 d = reg_of_var(c->dest, REG_ITMP3);
734 if (has_ext_instr_set) {
741 store_reg_to_var_int(c->dest, d);
745 s1 = var_to_reg_int(c->source1, REG_ITMP1);
746 d = reg_of_var(c->dest, REG_ITMP3);
747 M_ZAPNOT (s1, 0x03, d, 1);
748 store_reg_to_var_int(c->dest, d);
752 s1 = var_to_reg_int(c->source1, REG_ITMP1);
753 d = reg_of_var(c->dest, REG_ITMP3);
754 if (has_ext_instr_set) {
758 M_SLL ( s1, 48, d, 1);
759 M_SRA ( d, 48, d, 1);
761 store_reg_to_var_int(c->dest, d);
765 s1 = var_to_reg_int(c->source1, REG_ITMP1);
766 s2 = var_to_reg_int(c->source2, REG_ITMP2);
767 d = reg_of_var(c->dest, REG_ITMP3);
768 M_IADD (s1, s2, d, 0);
769 store_reg_to_var_int(c->dest, d);
772 s1 = var_to_reg_int(c->source1, REG_ITMP1);
773 s2 = var_to_reg_int(c->source2, REG_ITMP2);
774 d = reg_of_var(c->dest, REG_ITMP3);
775 M_LADD (s1, s2, d, 0);
776 store_reg_to_var_int(c->dest, d);
780 s1 = var_to_reg_int(c->source1, REG_ITMP1);
781 s2 = var_to_reg_int(c->source2, REG_ITMP2);
782 d = reg_of_var(c->dest, REG_ITMP3);
783 M_ISUB (s1, s2, d, 0);
784 store_reg_to_var_int(c->dest, d);
787 s1 = var_to_reg_int(c->source1, REG_ITMP1);
788 s2 = var_to_reg_int(c->source2, REG_ITMP2);
789 d = reg_of_var(c->dest, REG_ITMP3);
790 M_LSUB (s1, s2, d, 0);
791 store_reg_to_var_int(c->dest, d);
795 s1 = var_to_reg_int(c->source1, REG_ITMP1);
796 s2 = var_to_reg_int(c->source2, REG_ITMP2);
797 d = reg_of_var(c->dest, REG_ITMP3);
798 M_IMUL (s1, s2, d, 0);
799 store_reg_to_var_int(c->dest, d);
802 s1 = var_to_reg_int(c->source1, REG_ITMP1);
803 s2 = var_to_reg_int(c->source2, REG_ITMP2);
804 d = reg_of_var(c->dest, REG_ITMP3);
805 M_LMUL (s1, s2, d, 0);
806 store_reg_to_var_int(c->dest, d);
811 s1 = var_to_reg_int(c->source1, REG_ITMP1);
812 s2 = var_to_reg_int(c->source2, REG_ITMP2);
813 d = reg_of_var(c->dest, REG_ITMP3);
814 M_AND (s2, 0x1f, REG_ITMP3, 1);
815 M_SLL (s1, REG_ITMP3, d, 0);
816 M_IADD (d, REG_ZERO, d, 0);
817 store_reg_to_var_int(c->dest, d);
821 s1 = var_to_reg_int(c->source1, REG_ITMP1);
822 s2 = var_to_reg_int(c->source2, REG_ITMP2);
823 d = reg_of_var(c->dest, REG_ITMP3);
824 M_AND (s2, 0x1f, REG_ITMP3, 1);
825 M_SRA (s1, REG_ITMP3, d, 0);
826 store_reg_to_var_int(c->dest, d);
830 s1 = var_to_reg_int(c->source1, REG_ITMP1);
831 s2 = var_to_reg_int(c->source2, REG_ITMP2);
832 d = reg_of_var(c->dest, REG_ITMP3);
833 M_AND (s2, 0x1f, REG_ITMP2, 1);
834 M_ZAPNOT (s1, 0x0f, d, 1);
835 M_SRL ( d, REG_ITMP2, d, 0);
836 M_IADD ( d, REG_ZERO, d, 0);
837 store_reg_to_var_int(c->dest, d);
841 s1 = var_to_reg_int(c->source1, REG_ITMP1);
842 s2 = var_to_reg_int(c->source2, REG_ITMP2);
843 d = reg_of_var(c->dest, REG_ITMP3);
844 M_SLL (s1, s2, d, 0);
845 store_reg_to_var_int(c->dest, d);
849 s1 = var_to_reg_int(c->source1, REG_ITMP1);
850 s2 = var_to_reg_int(c->source2, REG_ITMP2);
851 d = reg_of_var(c->dest, REG_ITMP3);
852 M_SRA (s1, s2, d, 0);
853 store_reg_to_var_int(c->dest, d);
857 s1 = var_to_reg_int(c->source1, REG_ITMP1);
858 s2 = var_to_reg_int(c->source2, REG_ITMP2);
859 d = reg_of_var(c->dest, REG_ITMP3);
860 M_SRL (s1, s2, d, 0);
861 store_reg_to_var_int(c->dest, d);
866 s1 = var_to_reg_int(c->source1, REG_ITMP1);
867 s2 = var_to_reg_int(c->source2, REG_ITMP2);
868 d = reg_of_var(c->dest, REG_ITMP3);
869 M_AND (s1, s2, d, 0);
870 store_reg_to_var_int(c->dest, d);
875 s1 = var_to_reg_int(c->source1, REG_ITMP1);
876 s2 = var_to_reg_int(c->source2, REG_ITMP2);
877 d = reg_of_var(c->dest, REG_ITMP3);
879 store_reg_to_var_int(c->dest, d);
884 s1 = var_to_reg_int(c->source1, REG_ITMP1);
885 s2 = var_to_reg_int(c->source2, REG_ITMP2);
886 d = reg_of_var(c->dest, REG_ITMP3);
887 M_XOR (s1, s2, d, 0);
888 store_reg_to_var_int(c->dest, d);
893 s1 = var_to_reg_int(c->source1, REG_ITMP1);
894 s2 = var_to_reg_int(c->source2, REG_ITMP2);
895 d = reg_of_var(c->dest, REG_ITMP3);
896 M_CMPLT (s1, s2, REG_ITMP3, 0);
897 M_CMPLT (s2, s1, REG_ITMP1, 0);
898 M_LSUB (REG_ITMP1, REG_ITMP3, d, 0);
899 store_reg_to_var_int(c->dest, d);
903 /*********************** floating operations **************************/
906 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
907 d = reg_of_var(c->dest, REG_FTMP3);
909 store_reg_to_var_flt(c->dest, d);
912 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
913 d = reg_of_var(c->dest, REG_FTMP3);
915 store_reg_to_var_flt(c->dest, d);
919 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
920 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
921 d = reg_of_var(c->dest, REG_FTMP3);
923 store_reg_to_var_flt(c->dest, d);
926 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
927 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
928 d = reg_of_var(c->dest, REG_FTMP3);
930 store_reg_to_var_flt(c->dest, d);
934 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
935 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
936 d = reg_of_var(c->dest, REG_FTMP3);
938 store_reg_to_var_flt(c->dest, d);
941 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
942 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
943 d = reg_of_var(c->dest, REG_FTMP3);
945 store_reg_to_var_flt(c->dest, d);
949 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
950 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
951 d = reg_of_var(c->dest, REG_FTMP3);
953 store_reg_to_var_flt(c->dest, d);
956 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
957 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
958 d = reg_of_var(c->dest, REG_FTMP3);
960 store_reg_to_var_flt(c->dest, d);
964 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
965 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
966 d = reg_of_var(c->dest, REG_FTMP3);
968 store_reg_to_var_flt(c->dest, d);
971 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
972 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
973 d = reg_of_var(c->dest, REG_FTMP3);
975 store_reg_to_var_flt(c->dest, d);
979 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
980 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
981 d = reg_of_var(c->dest, REG_FTMP3);
982 M_FDIV ( s1,s2, REG_FTMP3 );
983 M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
984 M_CVTLF ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
985 M_FMUL ( REG_FTMP3, s2, REG_FTMP3 );
986 M_FSUB ( s1, REG_FTMP3, d);
987 store_reg_to_var_flt(c->dest, d);
990 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
991 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
992 d = reg_of_var(c->dest, REG_FTMP3);
993 M_DDIV ( s1,s2, REG_FTMP3 );
994 M_CVTDL_C ( REG_ZERO, REG_FTMP3, REG_FTMP3 ); /* round to integer */
995 M_CVTLD ( REG_ZERO, REG_FTMP3, REG_FTMP3 );
996 M_DMUL ( REG_FTMP3, s2, REG_FTMP3 );
997 M_DSUB ( s1, REG_FTMP3, d);
998 store_reg_to_var_flt(c->dest, d);
1003 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1004 d = reg_of_var(c->dest, REG_FTMP3);
1005 a = dseg_adddouble(0.0);
1006 M_LST (s1, REG_PV, a);
1007 M_DLD (d, REG_PV, a);
1008 M_CVTLF ( REG_ZERO, d, d);
1009 store_reg_to_var_flt(c->dest, d);
1014 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1015 d = reg_of_var(c->dest, REG_FTMP3);
1016 a = dseg_adddouble(0.0);
1017 M_LST (s1, REG_PV, a);
1018 M_DLD (d, REG_PV, a);
1019 M_CVTLD ( REG_ZERO, d, d);
1020 store_reg_to_var_flt(c->dest, d);
1025 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1026 d = reg_of_var(c->dest, REG_ITMP3);
1027 a = dseg_adddouble(0.0);
1028 M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
1029 M_DST (REG_FTMP1, REG_PV, a);
1030 M_ILD (d, REG_PV, a);
1031 store_reg_to_var_int(c->dest, d);
1036 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1037 d = reg_of_var(c->dest, REG_ITMP3);
1038 a = dseg_adddouble(0.0);
1039 M_CVTDL_C (REG_ZERO, s1, REG_FTMP1);
1040 M_DST (REG_FTMP1, REG_PV, a);
1041 M_LLD (d, REG_PV, a);
1042 store_reg_to_var_int(c->dest, d);
1046 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1047 d = reg_of_var(c->dest, REG_FTMP3);
1049 store_reg_to_var_flt(c->dest, d);
1053 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1054 d = reg_of_var(c->dest, REG_FTMP3);
1055 M_FADD (s1, REG_ZERO, d);
1056 store_reg_to_var_flt(c->dest, d);
1061 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1062 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
1063 d = reg_of_var(c->dest, REG_ITMP3);
1064 M_LSUB (REG_ZERO, 1, d, 1);
1065 M_FCMPEQ (s1, s2, REG_FTMP3);
1066 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1067 M_OR (REG_ZERO, REG_ZERO, d, 0);
1068 M_FCMPLT (s2, s1, REG_FTMP3);
1069 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1070 M_LADD (REG_ZERO, 1, d, 1);
1071 store_reg_to_var_int(c->dest, d);
1076 s1 = var_to_reg_flt(c->source1, REG_FTMP1);
1077 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
1078 d = reg_of_var(c->dest, REG_ITMP3);
1079 M_LADD (REG_ZERO, 1, d, 1);
1080 M_FCMPEQ (s1, s2, REG_FTMP3);
1081 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1082 M_OR (REG_ZERO, REG_ZERO, d, 0);
1083 M_FCMPLT (s1, s2, REG_FTMP3);
1084 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1085 M_LSUB (REG_ZERO, 1, d, 1);
1086 store_reg_to_var_int(c->dest, d);
1090 /********************** memory operations *****************************/
1092 case CMD_ARRAYLENGTH:
1093 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1094 d = reg_of_var(c->dest, REG_ITMP3);
1095 M_ILD (d, s1, OFFSET(java_arrayheader, size));
1096 store_reg_to_var_int(c->dest, d);
1100 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1101 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1102 d = reg_of_var(c->dest, REG_ITMP3);
1103 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1104 M_LLD ( d, REG_ITMP1, OFFSET (java_objectarray, data[0]));
1105 store_reg_to_var_int(c->dest, d);
1108 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1109 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1110 d = reg_of_var(c->dest, REG_ITMP3);
1111 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1112 M_LLD ( d, REG_ITMP1, OFFSET (java_longarray, data[0]));
1113 store_reg_to_var_int(c->dest, d);
1116 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1117 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1118 d = reg_of_var(c->dest, REG_ITMP3);
1119 M_S4ADDQ (s2, s1, REG_ITMP1, 0);
1120 M_ILD ( d, REG_ITMP1, OFFSET (java_intarray, data[0]));
1121 store_reg_to_var_int(c->dest, d);
1124 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1125 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1126 d = reg_of_var(c->dest, REG_FTMP3);
1127 M_S4ADDQ (s2, s1, REG_ITMP1, 0);
1128 M_FLD ( d, REG_ITMP1, OFFSET (java_floatarray, data[0]));
1129 store_reg_to_var_flt(c->dest, d);
1132 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1133 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1134 d = reg_of_var(c->dest, REG_FTMP3);
1135 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1136 M_DLD ( d, REG_ITMP1, OFFSET (java_doublearray, data[0]));
1137 store_reg_to_var_flt(c->dest, d);
1140 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1141 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1142 d = reg_of_var(c->dest, REG_ITMP3);
1143 if (has_ext_instr_set) {
1144 M_LADD (s2, s1, REG_ITMP1, 0);
1145 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1146 M_SLDU (d, REG_ITMP1, OFFSET (java_chararray, data[0]));
1149 M_LADD (s2, s1, REG_ITMP1, 0);
1150 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1151 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1152 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1153 M_EXTWL (REG_ITMP2, REG_ITMP1, d, 0);
1155 store_reg_to_var_int(c->dest, d);
1158 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1159 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1160 d = reg_of_var(c->dest, REG_ITMP3);
1161 if (has_ext_instr_set) {
1162 M_LADD (s2, s1, REG_ITMP1, 0);
1163 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1164 M_SLDU (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1168 M_LADD (s2, s1, REG_ITMP1, 0);
1169 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1170 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1171 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]) + 2);
1172 M_EXTQH (REG_ITMP2, REG_ITMP1, d, 0);
1173 M_SRA (d, 48, d, 1);
1175 store_reg_to_var_int(c->dest, d);
1178 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1179 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1180 d = reg_of_var(c->dest, REG_ITMP3);
1181 if (has_ext_instr_set) {
1182 M_LADD (s2, s1, REG_ITMP1, 0);
1183 M_BLDU (d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1187 M_LADD (s2, s1, REG_ITMP1, 0);
1188 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1189 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]) + 1);
1190 M_EXTQH (REG_ITMP2, REG_ITMP1, d, 0);
1191 M_SRA (d, 56, d, 1);
1193 store_reg_to_var_int(c->dest, d);
1197 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1198 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1199 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1200 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1201 M_LST (s3, REG_ITMP1, OFFSET (java_objectarray, data[0]));
1204 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1205 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1206 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1207 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1208 M_LST (s3, REG_ITMP1, OFFSET (java_longarray, data[0]));
1211 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1212 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1213 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1214 M_S4ADDQ (s2, s1, REG_ITMP1, 0);
1215 M_IST (s3, REG_ITMP1, OFFSET (java_intarray, data[0]));
1218 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1219 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1220 s3 = var_to_reg_flt(c->source3, REG_FTMP3);
1221 M_S4ADDQ (s2, s1, REG_ITMP1, 0);
1222 M_FST (s3, REG_ITMP1, OFFSET (java_floatarray, data[0]));
1225 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1226 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1227 s3 = var_to_reg_flt(c->source3, REG_FTMP3);
1228 M_S8ADDQ (s2, s1, REG_ITMP1, 0);
1229 M_DST (s3, REG_ITMP1, OFFSET (java_doublearray, data[0]));
1232 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1233 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1234 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1235 if (has_ext_instr_set) {
1236 M_LADD (s2, s1, REG_ITMP1, 0);
1237 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1238 M_SST (s3, REG_ITMP1, OFFSET (java_chararray, data[0]));
1241 M_LADD (s2, s1, REG_ITMP1, 0);
1242 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1243 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1244 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1245 M_INSWL (s3, REG_ITMP1, REG_ITMP3, 0);
1246 M_MSKWL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
1247 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
1248 M_LST_U (REG_ITMP2, REG_ITMP1, 0);
1252 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1253 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1254 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1255 if (has_ext_instr_set) {
1256 M_LADD (s2, s1, REG_ITMP1, 0);
1257 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1258 M_SST (s3, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1261 M_LADD (s2, s1, REG_ITMP1, 0);
1262 M_LADD (s2, REG_ITMP1, REG_ITMP1, 0);
1263 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1264 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1265 M_INSWL (s3, REG_ITMP1, REG_ITMP3, 0);
1266 M_MSKWL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
1267 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
1268 M_LST_U (REG_ITMP2, REG_ITMP1, 0);
1272 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1273 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1274 s3 = var_to_reg_int(c->source3, REG_ITMP3);
1275 if (has_ext_instr_set) {
1276 M_LADD (s2, s1, REG_ITMP1, 0);
1277 M_BST (s3, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1280 M_LADD (s2, s1, REG_ITMP1, 0);
1281 M_LLD_U (REG_ITMP2, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1282 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1283 M_INSBL (s3, REG_ITMP1, REG_ITMP3, 0);
1284 M_MSKBL (REG_ITMP2, REG_ITMP1, REG_ITMP2, 0);
1285 M_OR (REG_ITMP2, REG_ITMP3, REG_ITMP2, 0);
1286 M_LST_U (REG_ITMP2, REG_ITMP1, 0);
1292 switch (c->u.mem.type) {
1294 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1295 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1296 M_IST (s2, s1, c->u.mem.offset);
1300 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1301 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1302 M_LST (s2, s1, c->u.mem.offset);
1305 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1306 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
1307 M_FST (s2, s1, c->u.mem.offset);
1310 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1311 s2 = var_to_reg_flt(c->source2, REG_FTMP2);
1312 M_DST (s2, s1, c->u.mem.offset);
1314 default: panic ("internal error");
1319 switch (c->u.mem.type) {
1321 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1322 d = reg_of_var(c->dest, REG_ITMP3);
1323 M_ILD (d, s1, c->u.mem.offset);
1324 store_reg_to_var_int(c->dest, d);
1328 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1329 d = reg_of_var(c->dest, REG_ITMP3);
1330 M_LLD (d, s1, c->u.mem.offset);
1331 store_reg_to_var_int(c->dest, d);
1334 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1335 d = reg_of_var(c->dest, REG_FTMP1);
1336 M_FLD (d, s1, c->u.mem.offset);
1337 store_reg_to_var_flt(c->dest, d);
1340 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1341 d = reg_of_var(c->dest, REG_FTMP1);
1342 M_DLD (d, s1, c->u.mem.offset);
1343 store_reg_to_var_flt(c->dest, d);
1345 default: panic ("internal error");
1350 /********************** branch operations *****************************/
1353 mcode_addreference (c->u.bra.target);
1358 reginfo *di = c->dest->reg;
1360 if (di->typeflags & REG_INMEMORY)
1361 panic ("Can not put returnaddress into memory var");
1363 mcode_addreference (c->u.bra.target);
1369 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1370 M_RET (REG_ZERO, s1);
1376 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1377 mcode_addreference (c->u.bra.target);
1381 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1382 mcode_addreference (c->u.bra.target);
1386 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1387 mcode_addreference (c->u.bra.target);
1392 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1393 mcode_addreference (c->u.bra.target);
1397 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1398 mcode_addreference (c->u.bra.target);
1402 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1403 mcode_addreference (c->u.bra.target);
1409 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1410 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1411 M_CMPEQ (s1, s2, REG_ITMP1, 0);
1412 mcode_addreference (c->u.bra.target);
1413 M_BNEZ (REG_ITMP1, 0);
1417 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1418 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1419 M_CMPEQ (s1, s2, REG_ITMP1, 0);
1420 mcode_addreference (c->u.bra.target);
1421 M_BEQZ (REG_ITMP1, 0);
1424 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1425 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1426 M_CMPLT (s1, s2, REG_ITMP1, 0);
1427 mcode_addreference (c->u.bra.target);
1428 M_BNEZ (REG_ITMP1, 0);
1431 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1432 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1433 M_CMPLE (s1, s2, REG_ITMP1, 0);
1434 mcode_addreference ( c->u.bra.target );
1435 M_BEQZ (REG_ITMP1, 0);
1438 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1439 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1440 M_CMPLE (s1, s2, REG_ITMP1, 0);
1441 mcode_addreference (c->u.bra.target);
1442 M_BNEZ (REG_ITMP1, 0);
1445 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1446 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1447 M_CMPLT (s1, s2, REG_ITMP1, 0);
1448 mcode_addreference (c->u.bra.target);
1449 M_BEQZ (REG_ITMP1, 0);
1452 case CMD_IF_UCMPGE: /* branch if the unsigned value of s1 is
1453 greater that s2 (note, that s2 has
1455 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1456 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1457 M_CMPULE (s2, s1, REG_ITMP1, 0);
1458 mcode_addreference (c->u.bra.target);
1459 M_BNEZ (REG_ITMP1, 0);
1466 s1 = var_to_reg_int(c->source1, REG_RESULT);
1467 M_INTMOVE (s1, REG_RESULT);
1468 goto nowperformreturn;
1471 s1 = var_to_reg_flt(c->source1, REG_FRESULT);
1472 M_FLTMOVE (s1, REG_FRESULT);
1473 goto nowperformreturn;
1480 s2 = var_to_reg_int(c->source2, REG_ITMP2);
1481 M_INTMOVE (s2, REG_EXCEPTION);
1483 p = parentargs_base;
1485 {p--; M_LLD (REG_RA, REG_SP, 8*p);}
1486 for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
1487 if (!(intregs[r].typeflags & REG_ISUNUSED))
1488 {p--; M_LLD (r, REG_SP, 8*p);}
1489 for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
1490 if (!(floatregs[r].typeflags & REG_ISUNUSED))
1491 {p--; M_DLD (r, REG_SP, 8*p);}
1493 if (parentargs_base)
1494 {M_LDA (REG_SP, REG_SP, parentargs_base*8);}
1496 M_LDA (REG_SP, REG_SP, -32);
1497 M_LST(REG_RA, REG_SP, 0);
1498 M_LST(REG_RESULT, REG_SP, 8);
1499 M_DST(REG_FRESULT, REG_SP,16);
1500 M_LST(REG_EXCEPTION, REG_SP, 24);
1501 a = dseg_addaddress (method);
1502 M_LLD(INT_ARG_FST, REG_PV, a);
1503 M_OR(REG_RESULT, REG_RESULT, INT_ARG_FST + 1, 0);
1504 M_FLTMOVE(REG_FRESULT, FLT_ARG_FST + 2);
1505 a = dseg_addaddress ((void*) (builtin_displaymethodstop));
1506 M_LLD(REG_PV, REG_PV, a);
1507 M_JSR (REG_RA, REG_PV);
1508 if (mcodelen<=32768) M_LDA (REG_PV, REG_RA, -mcodelen);
1510 s4 ml=-mcodelen, mh=0;
1511 while (ml<-32768) { ml+=65536; mh--; }
1512 M_LDA (REG_PV, REG_RA, ml );
1513 M_LDAH (REG_PV, REG_PV, mh );
1515 M_LLD(REG_EXCEPTION, REG_SP, 24);
1516 M_DLD(REG_FRESULT, REG_SP,16);
1517 M_LLD(REG_RESULT, REG_SP, 8);
1518 M_LLD(REG_RA, REG_SP, 0);
1519 M_LDA (REG_SP, REG_SP, 32);
1521 M_RET (REG_ZERO, REG_RA);
1530 /* build jump table top down and use address of lowest entry */
1533 for (i = c->u.tablejump.targetcount - 1; i >= 0; i--) {
1534 a = dseg_addtarget (c->u.tablejump.targets[i]);
1538 /* last offset a returned by dseg_addtarget is used by load */
1540 s1 = var_to_reg_int(c->source1, REG_ITMP1);
1541 M_S8ADDQ (s1, REG_PV, REG_ITMP2, 0);
1542 M_LLD (REG_ITMP3, REG_ITMP2, a);
1543 M_JMP (REG_ZERO, REG_ITMP3);
1547 case CMD_INVOKESTATIC:
1548 case CMD_INVOKESPECIAL:
1549 case CMD_INVOKEVIRTUAL:
1550 case CMD_INVOKEINTERFACE:
1559 default: sprintf (logtext, "Unknown pseudo command: %d(%d)", c->opcode,
1566 /*********************** function input_args_prealloc **************************
1568 preallocates the input arguments (on the Alpha only for leaf methods)
1570 *******************************************************************************/
1573 static void input_args_prealloc()
1580 for (i = 0; (i < mparamnum) && (i < INT_ARG_CNT); i++) {
1583 p->saved = !isleafmethod;
1584 if (t==TYPE_DOUBLE || t==TYPE_FLOAT)
1585 r = &floatregs[FLT_ARG_FST + i];
1587 r = &intregs[INT_ARG_FST + i];
1588 r->typeflags &= ~REG_ISFREEUNUSED;
1594 /********************* function gen_computestackframe **************************
1596 computes the size and the layout of a stack frame.
1597 The values of localvars_base, savedregs_base, parentargs_base
1598 are numbers of 8-byte slots in the stackframe (every spilled or
1599 saved register value will be stored in a 64-bit slot, regardless
1600 of its type: INT/LONG/FLOAT/DOUBLE/ADDRESS)
1601 (a detailed description of the stack frame is contained in 'calling.doc')
1604 *******************************************************************************/
1607 static void gen_computestackframe()
1611 savedregs_num = (isleafmethod) ? 0 : 1; /* space to save the RA */
1613 /* space to save used callee saved registers */
1615 for (i = INT_SAV_FST; i < INT_SAV_FST + INT_SAV_CNT; i++)
1616 if (! (intregs[i].typeflags & REG_ISUNUSED))
1618 for (i = FLT_SAV_FST; i < FLT_SAV_FST + FLT_SAV_CNT; i++)
1619 if (! (floatregs[i].typeflags & REG_ISUNUSED))
1622 localvars_base = arguments_num;
1623 savedregs_base = localvars_base + localvars_num;
1624 parentargs_base = savedregs_base + savedregs_num;
1628 /******************** function gen_header **************************************
1630 using the data computed by gen_computestackframe it generates a function
1633 - saves the necessary registers
1634 - copies arguments to registers or to stack slots
1636 *******************************************************************************/
1639 static void gen_header ()
1645 /* create stack frame (if necessary) */
1647 if (parentargs_base)
1648 {M_LDA (REG_SP, REG_SP, -parentargs_base * 8);}
1650 /* save return address and used callee saved registers */
1652 p = parentargs_base;
1654 {p--; M_LST (REG_RA, REG_SP, 8*p);}
1655 for (r = INT_SAV_FST; r < INT_SAV_FST + INT_SAV_CNT; r++)
1656 if (!(intregs[r].typeflags & REG_ISUNUSED))
1657 {p--; M_LST (r, REG_SP, 8 * p);}
1658 for (r = FLT_SAV_FST; r < FLT_SAV_FST + FLT_SAV_CNT; r++)
1659 if (!(floatregs[r].typeflags & REG_ISUNUSED))
1660 {p--; M_DST (r, REG_SP, 8 * p);}
1662 /* take arguments out of register or stack frame */
1664 for (p = 0; p < mparamnum; p++) {
1665 ri = mparamvars[p]->reg;
1667 if (p < INT_ARG_CNT) { /* register arguments */
1668 if (IS_INT_LNG_REG(ri->typeflags)) { /* integer args */
1669 if (!(ri->typeflags & REG_INMEMORY)) /* reg arg -> register */
1670 M_INTMOVE (16+p, ri->num);
1671 else /* reg arg -> spilled */
1672 M_LST (16+p, REG_SP, 8 * (localvars_base + ri->num));
1674 else { /* floating args */
1675 if (!(ri->typeflags & REG_INMEMORY)) /* reg-arg -> register */
1676 M_FLTMOVE (16+p, ri->num);
1677 else /* reg-arg -> spilled */
1678 M_DST (16+p, REG_SP, 8 * (localvars_base + ri->num));
1682 else { /* stack arguments */
1683 pa = p - INT_ARG_CNT;
1684 if (IS_INT_LNG_REG(ri->typeflags)) { /* integer args */
1685 if (!(ri->typeflags & REG_INMEMORY)) /* stack arg -> register */
1686 M_LLD (ri->num, REG_SP, 8 * (parentargs_base + pa));
1687 else { /* stack arg -> spilled */
1688 M_LLD (REG_ITMP1, REG_SP, 8 * (parentargs_base + pa));
1689 M_LST (REG_ITMP1, REG_SP, 8 * (localvars_base + ri->num));
1693 if (!(ri->typeflags & REG_INMEMORY)) /* stack-arg -> register */
1694 M_DLD (ri->num, REG_SP, 8 * (parentargs_base + pa) );
1695 else { /* stack-arg -> spilled */
1696 M_DLD (REG_FTMP1, REG_SP, 8 * (parentargs_base + pa));
1697 M_DST (REG_FTMP1, REG_SP, 8 * (localvars_base + ri->num));
1702 } /* end gen_header */
1705 /************************ function gen_resolvebranch ***************************
1707 backpatches a branch instruction; Alpha branch instructions are very
1708 regular, so it is only necessary to overwrite some fixed bits in the
1711 parameters: mcodepiece .. start of code area
1712 sourcepos ... offset of branch instruction
1713 targetpos ... offset of branch target
1715 *******************************************************************************/
1718 static void gen_resolvebranch ( void* mcodepiece, s4 sourcepos, s4 targetpos)
1720 s4 *command = mcodepiece;
1721 s4 offset = targetpos - (sourcepos+4);
1723 (*command) |= ((offset >> 2) & ((s4) 0x1fffff) );
1728 /******** redefinition of code generation makros (compilinf into array) *******/
1731 These macros are newly defined to allow code generation into an array.
1732 This is necessary, because the original M_.. macros generate code by
1733 calling 'mcode_adds4' that uses an additional data structure to
1736 For a faster (but less flexible) version to generate code, these
1737 macros directly use the (s4* p) - pointer to put the code directly
1738 in a locally defined array.
1739 This makes sense only for the stub-generation-routines below.
1743 #define M_OP3(op,fu,a,b,c,const) \
1744 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<(16-3*(const)))| \
1745 ((const)<<12)|((fu)<<5)|((c)) )
1747 #define M_FOP3(op,fu,a,b,c) \
1748 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((fu)<<5)|(c) )
1750 #define M_BRA(op,a,disp) \
1751 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((disp)&0x1fffff) )
1753 #define M_MEM(op,a,b,disp) \
1754 *(p++) = ( (((s4)(op))<<26)|((a)<<21)|((b)<<16)|((disp)&0xffff) )
1759 /************************ function createcompilerstub **************************
1761 creates a stub routine which calls the compiler
1763 *******************************************************************************/
1765 #define COMPSTUBSIZE 3
1767 u1 *createcompilerstub (methodinfo *m)
1769 u8 *s = CNEW (u8, COMPSTUBSIZE); /* memory to hold the stub */
1770 s4 *p = (s4*) s; /* code generation pointer */
1772 /* code for the stub */
1773 M_LLD (REG_PV, REG_PV, 16); /* load pointer to the compiler */
1774 M_JMP (0, REG_PV); /* jump to the compiler, return address
1775 in reg 0 is used as method pointer */
1776 s[1] = (u8) m; /* literals to be adressed */
1777 s[2] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
1780 count_cstub_len += COMPSTUBSIZE * 8;
1787 /************************* function removecompilerstub *************************
1789 deletes a compilerstub from memory (simply by freeing it)
1791 *******************************************************************************/
1793 void removecompilerstub (u1 *stub)
1795 CFREE (stub, COMPSTUBSIZE * 8);
1799 /************************ function: removenativestub ***************************
1801 removes a previously created native-stub from memory
1803 *******************************************************************************/
1805 void removenativestub (u1 *stub)
1807 CFREE (stub, NATIVESTUBSIZE * 8);
1813 /********************* Funktion: createnativestub ******************************
1815 creates a stub routine which calls a native method
1817 *******************************************************************************/
1819 #define NATIVESTUBSIZE 11
1821 u1 *createnativestub (functionptr f, methodinfo *m)
1823 u8 *s = CNEW (u8, NATIVESTUBSIZE); /* memory to hold the stub */
1824 s4 *p = (s4*) s; /* code generation pointer */
1826 M_LDA (REG_SP, REG_SP, -8); /* build up stackframe */
1827 M_LST (REG_RA, REG_SP, 0); /* store return address */
1829 M_LLD (REG_PV, REG_PV, 6*8); /* load adress of native method */
1830 M_JSR (REG_RA, REG_PV); /* call native method */
1831 M_LDA (REG_PV, REG_RA, -4*4); /* recompute pv from ra */
1833 M_LLD (22, REG_PV, 7*8); /* get address of exceptionptr */
1834 M_LLD (REG_EXCEPTION, 22, 0); /* load exception into reg. 1 */
1835 M_LST (REG_ZERO, 22, 0); /* store NULL into exceptionptr */
1837 M_LLD (REG_RA, REG_SP, 0); /* load return address */
1838 M_LDA (REG_SP, REG_SP, 8); /* remove stackframe */
1840 M_RET (REG_ZERO, REG_RA); /* return to caller */
1842 s[6] = (u8) f; /* address of native method */
1843 s[7] = (u8) (&exceptionptr); /* address of exceptionptr */
1846 count_nstub_len += NATIVESTUBSIZE * 8;