4 # inssel-hppa.brg: burg file for special hppa instructions
6 # Copyright (c) 2007 Randolph Chung
8 # Permission is hereby granted, free of charge, to any person obtaining a copy
9 # of this software and associated documentation files (the "Software"), to deal
10 # in the Software without restriction, including without limitation the rights
11 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 # copies of the Software, and to permit persons to whom the Software is
13 # furnished to do so, subject to the following conditions:
15 # The above copyright notice and this permission notice shall be included in
16 # all copies or substantial portions of the Software.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 # Load/store operations
28 reg: CEE_LDIND_I1 (OP_REGVAR) {
29 MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg);
32 reg: CEE_LDIND_I2 (OP_REGVAR) {
33 MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg);
36 reg: CEE_LDIND_REF (OP_REGVAR),
37 reg: CEE_LDIND_I (OP_REGVAR),
38 reg: CEE_LDIND_I4 (OP_REGVAR),
39 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
40 state->reg1 = state->left->tree->dreg;
41 tree->dreg = state->reg1;
44 lreg: CEE_LDIND_I8 (OP_REGVAR) {
45 /* reg2 contains the most significant word */
46 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, state->left->tree->dreg);
47 tree->opcode = OP_MOVE;
48 tree->dreg = state->reg1;
49 tree->sreg1 = state->left->tree->dreg + 1;
50 mono_bblock_add_inst (s->cbb, tree);
53 freg: CEE_LDIND_R4 (OP_REGVAR) {
54 MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
57 freg: CEE_LDIND_R8 (OP_REGVAR) {
58 MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
61 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
62 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
65 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
66 /* this should only happen for methods returning a long */
67 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
68 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg + 1, state->right->reg2);
72 stmt: OP_OUTARG (reg) {
73 MonoCallInst *call = tree->inst_call;
74 MonoHPPAArgInfo *ai = tree->backend.data;
76 tree->opcode = OP_SETREG;
77 tree->dreg = mono_regstate_next_int (s->rs);
78 tree->sreg1 = state->left->reg1;
79 mono_bblock_add_inst (s->cbb, tree);
80 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE);
83 stmt: OP_HPPA_OUTARG_REGOFFSET (base) {
84 MonoCallInst *call = tree->inst_call;
86 tree->inst_basereg = state->left->tree->inst_basereg;
87 tree->inst_offset = state->left->tree->inst_offset;
88 tree->dreg = mono_regstate_next_int (s->rs);
89 mono_bblock_add_inst (s->cbb, tree);
91 mono_call_inst_add_outarg_reg (s, call, tree->dreg, hppa_r28, FALSE);
94 stmt: OP_OUTARG (OP_REGVAR) {
95 MonoCallInst *call = tree->inst_call;
96 MonoHPPAArgInfo *ai = tree->backend.data;
98 tree->opcode = OP_SETREG;
99 tree->dreg = mono_regstate_next_int (s->rs);
100 tree->sreg1 = state->left->tree->dreg;
101 mono_bblock_add_inst (s->cbb, tree);
102 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE);
105 stmt: OP_OUTARG (lreg) {
106 MonoCallInst *call = tree->inst_call;
107 MonoHPPAArgInfo *ai = tree->backend.data;
108 int tdreg = mono_regstate_next_int (s->rs);
110 MONO_EMIT_NEW_UNALU (s, OP_SETREG, tdreg, state->left->reg2);
111 mono_call_inst_add_outarg_reg (s, call, tdreg, ai->reg, FALSE);
112 tree->opcode = OP_SETREG;
113 tree->dreg = mono_regstate_next_int (s->rs);
114 tree->sreg1 = state->left->reg1;
115 mono_bblock_add_inst (s->cbb, tree);
116 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg + 1, FALSE);
119 stmt: OP_OUTARG (OP_ICONST) {
120 MonoCallInst *call = tree->inst_call;
121 MonoHPPAArgInfo *ai = tree->backend.data;
123 tree->opcode = OP_ICONST;
124 tree->dreg = mono_regstate_next_int (s->rs);
125 tree->inst_c0 = state->left->tree->inst_c0;
126 mono_bblock_add_inst (s->cbb, tree);
127 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE);
130 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
131 MonoCallInst *call = tree->inst_call;
132 MonoHPPAArgInfo *ai = tree->backend.data;
134 tree->opcode = OP_SETREG;
135 tree->dreg = mono_regstate_next_int (s->rs);
136 tree->sreg1 = state->left->left->tree->dreg;
137 mono_bblock_add_inst (s->cbb, tree);
138 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE);
141 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) "0" {
142 MonoCallInst *call = tree->inst_call;
143 MonoHPPAArgInfo *ai = tree->backend.data;
144 int start_reg = ai->reg;
146 int nregs = (size + (sizeof (gpointer) - 1)) / sizeof (gpointer);
147 int i, tmpr, soffset, dreg;
148 MonoInst *vt = state->left->left->tree;
149 soffset = vt->inst_offset;
151 if (ai->pass_in_reg) {
152 for (i = 0; i < nregs; ++i) {
153 tmpr = mono_regstate_next_int (s->rs);
154 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset);
155 dreg = mono_regstate_next_int (s->rs);
156 if (size < sizeof (gpointer))
157 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, dreg, tmpr, (sizeof (gpointer) - size) * 8);
159 MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, tmpr);
160 mono_call_inst_add_outarg_reg (s, call, dreg, start_reg + i, FALSE);
161 soffset += sizeof (gpointer);
162 size -= sizeof (gpointer);
166 mini_emit_memcpy (s, hppa_sp, ai->offset, vt->inst_basereg, soffset, size, 0);
170 stmt: OP_OUTARG_R4 (freg) {
171 MonoCallInst *call = tree->inst_call;
173 tree->opcode = OP_HPPA_SETF4REG;
174 tree->dreg = mono_regstate_next_float (s->rs);
175 tree->sreg1 = state->left->reg1;
176 mono_bblock_add_inst (s->cbb, tree);
177 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
180 stmt: OP_OUTARG_R4 (OP_R4CONST) {
181 MonoCallInst *call = tree->inst_call;
183 tree->opcode = OP_HPPA_OUTARG_R4CONST;
184 tree->dreg = mono_regstate_next_float (s->rs);
185 tree->inst_p0 = state->left->tree->inst_p0;
186 mono_bblock_add_inst (s->cbb, tree);
187 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
190 stmt: OP_OUTARG_R8 (freg),
191 stmt: OP_OUTARG (freg) {
192 MonoCallInst *call = tree->inst_call;
194 tree->opcode = OP_SETFREG;
195 tree->dreg = mono_regstate_next_float (s->rs);
196 tree->sreg1 = state->left->reg1;
197 mono_bblock_add_inst (s->cbb, tree);
198 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
201 stmt: OP_OUTARG_MEMBASE (reg) {
202 MonoHPPAArgInfo *ai = tree->backend.data;
206 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1);
209 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1);
212 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1);
215 g_assert_not_reached ();
219 stmt: OP_OUTARG_MEMBASE (OP_ICONST) {
220 MonoHPPAArgInfo *ai = tree->backend.data;
224 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI1_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0);
227 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI2_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0);
230 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0);
233 g_assert_not_reached ();
237 stmt: OP_OUTARG_MEMBASE (lreg) {
238 MonoHPPAArgInfo *ai = tree->backend.data;
239 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg2);
240 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset + 4, state->left->reg1);
243 stmt: OP_OUTARG_MEMBASE (freg) {
244 MonoHPPAArgInfo *ai = tree->backend.data;
246 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1);
248 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1);
251 stmt: OP_OUTARG_MEMBASE (OP_R4CONST) {
252 MonoHPPAArgInfo *ai = tree->backend.data;
253 unsigned int constaddr = mono_regstate_next_int (s->rs);
254 unsigned int tmp = mono_regstate_next_float (s->rs);
255 MONO_EMIT_NEW_ICONST (s, constaddr, (unsigned int)state->left->tree->inst_p0);
256 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, tmp, constaddr, 0);
257 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_LEFT, hppa_sp, ai->offset, tmp);
260 reg: OP_LOCALLOC (OP_ICONST) {
261 tree->sreg1 = mono_regstate_next_int (s->rs);
262 tree->dreg = state->reg1;
263 MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
264 mono_bblock_add_inst (s->cbb, tree);
267 reg: OP_LOCALLOC (reg) {
268 tree->dreg = state->reg1;
269 tree->sreg1 = state->left->reg1;
270 mono_bblock_add_inst (s->cbb, tree);
273 stmt: OP_SETRET (reg) {
274 tree->opcode = OP_MOVE;
275 tree->sreg1 = state->left->reg1;
276 tree->dreg = hppa_r28;
277 mono_bblock_add_inst (s->cbb, tree);
280 stmt: OP_SETRET (lreg) {
281 tree->opcode = OP_SETLRET;
282 tree->sreg1 = state->left->reg1;
283 tree->sreg2 = state->left->reg2;
284 tree->dreg = hppa_r28;
285 mono_bblock_add_inst (s->cbb, tree);
288 stmt: OP_SETRET (freg) {
289 if (mono_method_signature (s->method)->ret->type == MONO_TYPE_R4) {
290 tree->opcode = OP_HPPA_SETF4REG;
292 tree->opcode = OP_SETFREG;
295 tree->sreg1 = state->left->reg1;
296 tree->dreg = hppa_fr4;
297 mono_bblock_add_inst (s->cbb, tree);
300 # Comparision rules: hppa does not have an addressable status register, so
301 # we have to do compare-and-branch in a single step
303 # Override the cost of the rule in the base inssel.brg so that this is preferred
304 # We are using this so that all the combinations of OP_COMPARE(reg, OP_ICONST)
305 # will get folded into OP_COMPARE(reg, reg) to simplify our compare-and-branch
307 # FIXME: this is ugly, we should expand the rules here, or try to refactor
308 # the rules in the base set
310 tree->dreg = state->reg1;
311 MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0);
314 stmt: OP_SWITCH (reg) {
315 MonoInst *label, *inst;
316 int n = GPOINTER_TO_INT (tree->klass);
317 int sreg = mono_regstate_next_int (s->rs);
319 MONO_NEW_LABEL (s, label);
321 MONO_EMIT_NEW_ICONST (s, sreg, n);
323 MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(s, CEE_BGE_UN, state->left->reg1, sreg, tree->inst_many_bb [n]);
324 mono_bblock_add_inst (s->cbb, label);
325 mono_create_jump_table (s, label, tree->inst_many_bb, n);
326 /* the backend code will deal with aot vs normal case */
327 tree->sreg1 = state->left->reg1;
328 mono_bblock_add_inst (s->cbb, tree);
331 stmt: CEE_BEQ (OP_COMPARE(reg, reg)),
332 stmt: CEE_BNE_UN (OP_COMPARE(reg, reg)),
333 stmt: CEE_BGE (OP_COMPARE(reg, reg)),
334 stmt: CEE_BGE_UN (OP_COMPARE(reg, reg)),
335 stmt: CEE_BGT (OP_COMPARE(reg, reg)),
336 stmt: CEE_BGT_UN (OP_COMPARE(reg, reg)),
337 stmt: CEE_BLE (OP_COMPARE(reg, reg)),
338 stmt: CEE_BLE_UN (OP_COMPARE(reg, reg)),
339 stmt: CEE_BLT (OP_COMPARE(reg, reg)),
340 stmt: CEE_BLT_UN (OP_COMPARE(reg, reg)) "0" {
341 tree->opcode = OP_HPPA_BEQ + (tree->opcode - CEE_BEQ);
342 tree->sreg1 = state->left->left->reg1;
343 tree->sreg2 = state->left->right->reg1;
344 tree->inst_offset = state->left->left->tree->inst_offset;
345 mono_bblock_add_inst (s->cbb, tree);
348 reg: OP_CEQ (OP_COMPARE (reg, reg)),
349 reg: OP_CGT (OP_COMPARE (reg, reg)),
350 reg: OP_CGT_UN (OP_COMPARE (reg, reg)),
351 reg: OP_CLT (OP_COMPARE (reg, reg)),
352 reg: OP_CLT_UN (OP_COMPARE (reg, reg)) "0" {
353 MONO_EMIT_BIALU (s, tree, OP_HPPA_CEQ + (tree->opcode - OP_CEQ), state->reg1, state->left->left->reg1, state->left->right->reg1);
356 reg: OP_CEQ (OP_COMPARE_IMM (reg, OP_ICONST)),
357 reg: OP_CLT (OP_COMPARE_IMM (reg, OP_ICONST)),
358 reg: OP_CLT_UN (OP_COMPARE_IMM (reg, OP_ICONST)),
359 reg: OP_CGT (OP_COMPARE_IMM (reg, OP_ICONST)),
360 reg: OP_CGT_UN (OP_COMPARE_IMM (reg, OP_ICONST)) "0" {
361 MONO_EMIT_BIALU_IMM (s, tree, OP_HPPA_CEQ_IMM + (tree->opcode - OP_CEQ), state->reg1, state->left->left->reg1, state->left->right->reg1);
364 # Floating point versions of the compare functions
365 stmt: CEE_BEQ (OP_COMPARE (freg, freg)),
366 stmt: CEE_BNE_UN (OP_COMPARE (freg, freg)),
367 stmt: CEE_BLT (OP_COMPARE (freg, freg)),
368 stmt: CEE_BLT_UN (OP_COMPARE (freg, freg)),
369 stmt: CEE_BGT (OP_COMPARE (freg, freg)),
370 stmt: CEE_BGT_UN (OP_COMPARE (freg, freg)),
371 stmt: CEE_BGE (OP_COMPARE (freg, freg)),
372 stmt: CEE_BGE_UN (OP_COMPARE (freg, freg)),
373 stmt: CEE_BLE (OP_COMPARE (freg, freg)),
374 stmt: CEE_BLE_UN (OP_COMPARE (freg, freg)) "0" {
375 tree->opcode = OP_FBEQ + (tree->opcode - CEE_BEQ);
376 tree->sreg1 = state->left->left->reg1;
377 tree->sreg2 = state->left->right->reg1;
378 mono_bblock_add_inst (s->cbb, tree);
381 reg: OP_CEQ (OP_COMPARE (freg, freg)),
382 reg: OP_CGT (OP_COMPARE (freg, freg)),
383 reg: OP_CGT_UN (OP_COMPARE (freg, freg)),
384 reg: OP_CLT (OP_COMPARE (freg, freg)),
385 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) "0" {
386 tree->opcode = OP_FCEQ + (tree->opcode - OP_CEQ);
387 tree->sreg1 = state->left->left->reg1;
388 tree->sreg2 = state->left->right->reg1;
389 tree->dreg = state->reg1;
390 mono_bblock_add_inst (s->cbb, tree);
394 reg: CEE_ADD_OVF (reg, reg),
395 reg: CEE_ADD_OVF_UN (reg, reg) "0" {
396 tree->backend.reg3 = tree->opcode;
397 tree->opcode = OP_HPPA_ADD_OVF;
398 tree->sreg1 = state->left->reg1;
399 tree->sreg2 = state->right->reg1;
400 tree->dreg = state->reg1;
401 mono_bblock_add_inst (s->cbb, tree);
404 lreg: OP_LADD_OVF (lreg, lreg),
405 lreg: OP_LADD_OVF_UN (lreg, lreg) "0" {
406 MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1);
407 tree->backend.reg3 = tree->opcode;
408 tree->opcode = OP_HPPA_ADDC_OVF;
409 tree->sreg1 = state->left->reg2;
410 tree->sreg2 = state->right->reg2;
411 tree->dreg = state->reg2;
412 mono_bblock_add_inst (s->cbb, tree);
415 reg: CEE_SUB_OVF (reg, reg),
416 reg: CEE_SUB_OVF_UN (reg, reg) "0" {
417 MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
418 tree->backend.reg3 = tree->opcode;
419 tree->opcode = OP_HPPA_SUB_OVF;
420 tree->sreg1 = state->left->reg1;
421 tree->sreg2 = state->right->reg1;
422 tree->dreg = state->reg1;
423 mono_bblock_add_inst (s->cbb, tree);
426 lreg: OP_LSUB_OVF (lreg, lreg),
427 lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
428 MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
429 tree->backend.reg3 = tree->opcode;
430 tree->opcode = OP_HPPA_SUBB_OVF;
431 tree->sreg1 = state->left->reg2;
432 tree->sreg2 = state->right->reg2;
433 tree->dreg = state->reg2;
434 mono_bblock_add_inst (s->cbb, tree);
437 lreg: OP_LNEG (lreg) "2" {
438 MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, hppa_r0, state->left->reg1);
439 MONO_EMIT_BIALU (s, tree, OP_SBB, state->reg2, hppa_r0, state->left->reg2);
442 reg: CEE_MUL (reg, reg),
443 reg: CEE_MUL_OVF (reg, reg),
444 reg: CEE_MUL_OVF_UN (reg, reg) "0" {
445 guint32 sreg1 = state->left->reg1;
446 guint32 sreg2 = state->right->reg1;
447 guint32 dreg = state->reg1;
448 guint32 freg1, freg2, freg3;
450 freg1 = mono_regstate_next_float (s->rs);
451 freg2 = mono_regstate_next_float (s->rs);
452 freg3 = mono_regstate_next_float (s->rs);
454 /* TODO: this scribbles on 4-bytes past the end of the stack; need
455 * to figure out how to properly "reserve" a temp stack slot for
458 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg1);
459 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, freg1, hppa_sp, 0);
460 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg2);
461 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, freg2, hppa_sp, 0);
462 MONO_EMIT_NEW_BIALU (s, OP_HPPA_XMPYU, freg3, freg1, freg2);
463 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_RIGHT, hppa_sp, 0, freg3);
464 MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, hppa_sp, 0);
467 reg: CEE_MUL(reg, OP_ICONST),
468 reg: OP_MUL_IMM(reg, OP_ICONST),
469 reg: CEE_MUL_OVF (reg, OP_ICONST),
470 reg: CEE_MUL_OVF_UN (reg, OP_ICONST) "0" {
471 guint32 sreg1 = state->left->reg1;
472 gssize imm = state->right->tree->inst_c0;
473 guint32 dreg = state->reg1;
474 guint32 freg1, freg2, freg3;
476 freg1 = mono_regstate_next_float (s->rs);
477 freg2 = mono_regstate_next_float (s->rs);
478 freg3 = mono_regstate_next_float (s->rs);
480 /* TODO: this scribbles on 4-bytes past the end of the stack; need
481 * to figure out how to properly "reserve" a temp stack slot for
484 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg1);
485 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, freg1, hppa_sp, 0);
486 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, hppa_sp, 0, imm);
487 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, freg2, hppa_sp, 0);
488 MONO_EMIT_NEW_BIALU (s, OP_HPPA_XMPYU, freg3, freg1, freg2);
489 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_RIGHT, hppa_sp, 0, freg3);
490 MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, hppa_sp, 0);
493 # Floating point ALU ops
494 freg: OP_FNEG (freg) "0" {
495 extern double hppa_zero;
496 MonoInst *inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
497 inst->opcode = OP_R8CONST;
498 inst->dreg = mono_regstate_next_float (s->rs);
499 inst->inst_p0 = (gpointer)&hppa_zero;
500 mono_bblock_add_inst (s->cbb, inst);
501 MONO_EMIT_BIALU (s, tree, OP_FSUB, state->reg1, inst->dreg, state->left->reg1);
504 # Conversion operations
505 lreg: CEE_CONV_I8 (reg) "0" {
506 int tmpreg = mono_regstate_next_int (s->rs);
507 int negone = mono_regstate_next_int (s->rs);
511 * tmp = low > -1 ? 1: 0;
512 * high = tmp - 1; if low is zero or pos high becomes 0, else -1
514 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
515 MONO_EMIT_NEW_ICONST (s, negone, -1);
516 MONO_EMIT_NEW_BIALU (s, OP_HPPA_CGT, tmpreg, state->reg1, negone);
517 MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, 1);
520 freg: OP_LCONV_TO_R8 (lreg) {
521 tree->sreg1 = state->left->reg1;
522 tree->dreg = state->reg1;
523 mono_bblock_add_inst (s->cbb, tree);
526 freg: OP_LCONV_TO_R8 (lreg) {
530 freg: OP_LCONV_TO_R4 (lreg) {
531 tree->sreg1 = state->left->reg1;
532 tree->dreg = state->reg1;
533 mono_bblock_add_inst (s->cbb, tree);
536 reg: OP_LCONV_TO_OVF_I (lreg),
537 reg: OP_LCONV_TO_OVF_I4 (lreg) "0" {
538 int tmp_reg = mono_regstate_next_int (s->rs);
540 /* Overflows if reg2 != sign extension of reg1 */
541 MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, tmp_reg, state->left->reg1, 31);
543 MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, state->left->reg2, tmp_reg, "OverflowException");
544 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
549 stmt: OP_START_HANDLER {
550 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
551 tree->inst_left = spvar;
552 mono_bblock_add_inst (s->cbb, tree);
555 stmt: OP_ENDFINALLY {
556 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
557 tree->inst_left = spvar;
558 mono_bblock_add_inst (s->cbb, tree);
561 stmt: OP_ENDFILTER (reg) {
562 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
563 tree->inst_left = spvar;
564 tree->sreg1 = state->left->reg1;
565 mono_bblock_add_inst (s->cbb, tree);