pike.git
/
src
/
code
/
sparc.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/code/sparc.c:1:
/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
-
|| $Id: sparc.c,v 1.
25
2002/11/08
12
:
22
:
52
grubba Exp $
+
|| $Id: sparc.c,v 1.
26
2002/11/08
17
:
29
:
59
grubba Exp $
*/ /* * Machine code generator for sparc. * * Henrik Grubbström 20010720 */
-
+
#include "global.h"
+
#include "svalue.h"
#include "operators.h"
-
+
#include "object.h"
/* * Register definitions */ #define SPARC_REG_G0 0 #define SPARC_REG_G1 1 #define SPARC_REG_G2 2 #define SPARC_REG_G3 3 #define SPARC_REG_G4 4
pike.git/src/code/sparc.c:178:
* * O6 Stack Pointer * O7 Program Counter * */ #define SPARC_REG_PIKE_IP SPARC_REG_L0 #define SPARC_REG_PIKE_FP SPARC_REG_L1 #define SPARC_REG_PIKE_SP SPARC_REG_L2 #define SPARC_REG_PIKE_MARK_SP SPARC_REG_L3
+
#define SPARC_REG_PIKE_OBJ SPARC_REG_L4
#define SPARC_REG_SP SPARC_REG_O6 #define SPARC_REG_PC SPARC_REG_O7 /* * Code generator state. */ unsigned INT32 sparc_codegen_state = 0; int sparc_last_pc = 0; #define LOAD_PIKE_INTERPRETER() do { \
pike.git/src/code/sparc.c:326:
SPARC_STW(SPARC_REG_G0, SPARC_REG_PIKE_SP, e, 1); } } if (x) { SET_REG(SPARC_REG_I1, x); SPARC_STW(SPARC_REG_I1, SPARC_REG_PIKE_SP, OFFSETOF(svalue, u.integer), 1); } else { SPARC_STW(SPARC_REG_G0, SPARC_REG_PIKE_SP, OFFSETOF(svalue, u.integer), 1); } if (x != type_word) {
-
SET_REG(SPARC_REG_
I0
, type_word);
+
SET_REG(SPARC_REG_
I1
, type_word);
} /* This is safe since type_word is never zero. */
-
/* stw %
i0
, [ %pike_sp ] */
-
SPARC_STW(SPARC_REG_
I0
, SPARC_REG_PIKE_SP, 0, 1);
+
/* stw %
i1
, [ %pike_sp ] */
+
SPARC_STW(SPARC_REG_
I1
, SPARC_REG_PIKE_SP, 0, 1);
/* add %pike_sp, %pike_sp, sizeof(struct svalue) */ SPARC_ADD(SPARC_REG_PIKE_SP, SPARC_REG_PIKE_SP, sizeof(struct svalue), 1); sparc_codegen_state |= SPARC_CODEGEN_SP_NEEDS_STORE; } static void sparc_clear_string_subtype(void) { LOAD_PIKE_SP(); /* lduh [ %pike_sp, %g0 ], %i0 */ SPARC_LDUH(SPARC_REG_I0, SPARC_REG_PIKE_SP, OFFSETOF(svalue, type), 1); /* subcc %g0, %i0, 8 */ SPARC_SUBcc(SPARC_REG_G0, SPARC_REG_I0, PIKE_T_INT, 1); /* be,a .+8 */ SPARC_BE(8, 1); /* sth %g0, [ %pike_sp, 2 ] */ SPARC_STH(SPARC_REG_G0, SPARC_REG_PIKE_SP, OFFSETOF(svalue, subtype), 1); }
-
+
static void sparc_push_lfun(unsigned int no)
+
{
+
LOAD_PIKE_FP();
+
LOAD_PIKE_SP();
+
/* lduw [ %pike_fp, %offset(pike_frame, current_object) ], %pike_obj */
+
SPARC_LDUW(SPARC_REG_PIKE_OBJ, SPARC_REG_PIKE_FP,
+
OFFSETOF(pike_frame, current_object), 1);
+
/* stw %pike_obj, [ %pike_sp, %offset(svalue, u.object) ] */
+
SPARC_STW(SPARC_REG_PIKE_OBJ, SPARC_REG_PIKE_SP,
+
OFFSETOF(svalue, u.object), 1);
+
/* lduw [ %pike_obj, %offset(object, refs) ], %i0 */
+
SPARC_LDUW(SPARC_REG_I0, SPARC_REG_PIKE_OBJ,
+
OFFSETOF(object, refs), 1);
+
/* add %i0, 1, %i0 */
+
SPARC_ADD(SPARC_REG_I0, SPARC_REG_I0, 1, 1);
+
/* stw %i0, [ %pike_obj, %offset(object, refs) ] */
+
SPARC_STW(SPARC_REG_I0, SPARC_REG_PIKE_OBJ,
+
OFFSETOF(object, refs), 1);
+
/* lduh [ %pike_fp, %offset(pike_frame, context.identifier_level ], %i1 */
+
SPARC_LDUH(SPARC_REG_I1, SPARC_REG_PIKE_FP,
+
OFFSETOF(pike_frame, context.identifier_level), 1);
+
SET_REG(SPARC_REG_I2, (no & 0xffff) | (PIKE_T_FUNCTION << 16));
+
/* add %i1, %i2, %i1 */
+
SPARC_ADD(SPARC_REG_I1, SPARC_REG_I1, SPARC_REG_I2, 0);
+
/* stw %i1, [ %pike_sp, %g0 ] */
+
SPARC_STW(SPARC_REG_I1, SPARC_REG_PIKE_SP, SPARC_REG_G0, 0);
+
/* add %pike_sp, sizeof(struct svalue), %pike_sp */
+
SPARC_ADD(SPARC_REG_PIKE_SP, SPARC_REG_PIKE_SP, sizeof(struct svalue), 1);
+
sparc_codegen_state |= SPARC_CODEGEN_SP_NEEDS_STORE;
+
}
+
+
void sparc_local_lvalue(unsigned int no)
+
{
+
LOAD_PIKE_SP();
+
LOAD_PIKE_FP();
+
SET_REG(SPARC_REG_I0, T_LVALUE);
+
/* sth %i0, [ %pike_sp, %g0 ] */
+
SPARC_STH(SPARC_REG_I0, SPARC_REG_PIKE_SP, SPARC_REG_G0, 0);
+
SET_REG(SPARC_REG_I1, no * sizeof(struct svalue));
+
/* lduw [ %pike_fp, %offset(pike_frame, locals) ], %i2 */
+
SPARC_LDUW(SPARC_REG_I2, SPARC_REG_PIKE_FP,
+
OFFSETOF(pike_frame, locals), 1);
+
SET_REG(SPARC_REG_I0, T_VOID);
+
/* stw %i2, [ %pike_sp, %offset(svalue, u.lval) ] */
+
SPARC_STW(SPARC_REG_I2, SPARC_REG_PIKE_SP,
+
OFFSETOF(svalue, u.lval), 1);
+
/* add %pike_sp, sizeof(struct svalue) * 2, %pike_sp */
+
SPARC_ADD(SPARC_REG_PIKE_SP, SPARC_REG_PIKE_SP, sizeof(struct svalue)*2, 1);
+
/* sth %i0, [ %pike_sp , -sizeof(struct svalue) ] */
+
SPARC_STH(SPARC_REG_I0, SPARC_REG_PIKE_SP, -sizeof(struct svalue), 1);
+
sparc_codegen_state |= SPARC_CODEGEN_SP_NEEDS_STORE;
+
}
+
/* * */
-
+
static void low_ins_call(void *addr, int delay_ok)
+
{
+
SPARC_FLUSH_UNSTORED();
+
+
{
+
static int last_prog_id=-1;
+
static size_t last_num_linenumbers=(size_t)~0;
+
if(last_prog_id != Pike_compiler->new_program->id ||
+
last_num_linenumbers != Pike_compiler->new_program->num_linenumbers)
+
{
+
last_prog_id=Pike_compiler->new_program->id;
+
last_num_linenumbers = Pike_compiler->new_program->num_linenumbers;
+
+
LOAD_PIKE_FP();
+
+
/* Note: We fill the delay slot with the following opcode.
+
* This works since the new %o7 is available immediately.
+
* (Sparc Architecture Manual V9 p149.)
+
*/
+
+
/* stw %o7, [ %pike_fp, %offsetof(pike_frame, pc) ] */
+
add_to_program(0xc0202000|(SPARC_REG_O7<<25)|(SPARC_REG_PIKE_FP<<14)|
+
OFFSETOF(pike_frame, pc));
+
+
delay_ok = 1;
+
}
+
}
+
+
ADD_CALL(addr, delay_ok);
+
+
/* This is probably only needed for some instructions, but... */
+
SPARC_UNLOAD_CACHED();
+
}
+
static void low_ins_f_byte(unsigned int b, int delay_ok) { void *addr; #ifdef PIKE_DEBUG if(store_linenumbers && b<F_MAX_OPCODE) ADD_COMPILED(b); #endif /* PIKE_DEBUG */ b-=F_OFFSET;
pike.git/src/code/sparc.c:376:
#endif addr = instrs[b].address; #ifdef PIKE_DEBUG if (d_flag < 3) #endif /* This is not very pretty */ switch(b) {
+
#if 0
case F_MARK2 - F_OFFSET: sparc_mark(0); /* FALL_THROUGH */ case F_SYNCH_MARK - F_OFFSET: case F_MARK - F_OFFSET: sparc_mark(0); return; case F_POP_MARK - F_OFFSET: sparc_incr_mark_sp(-1); return;
pike.git/src/code/sparc.c:409:
case F_MARK_AND_CONST1 - F_OFFSET: sparc_mark(0); sparc_push_int(1, 0); return; case F_CONST_1 - F_OFFSET: sparc_push_int(-1, 0); return; case F_BIGNUM - F_OFFSET: sparc_push_int(0x7fffffff, 0); return;
+
#endif /* 0 */
+
+
#define F_ALIAS(F_FUN, O_FUN) \
+
case F_FUN - F_OFFSET: \
+
addr = (void *)O_FUN; \
+
break
+
case F_MAKE_ITERATOR - F_OFFSET: { extern void f_Iterator(INT32); SET_REG(SPARC_REG_O0, 1); delay_ok = 1; addr = (void *)f_Iterator; } break;
-
#define F_ALIAS(F_FUN, O_FUN) \
-
case F_FUN - F_OFFSET: \
-
addr = (void *)O_FUN; \
-
break
-
+
F_ALIAS(F_COMPL, o_compl); F_ALIAS(F_LSH, o_lsh); F_ALIAS(F_RSH, o_rsh); case F_ADD - F_OFFSET: SET_REG(SPARC_REG_O0, 2); delay_ok = 1; addr = (void *)f_add; break; F_ALIAS(F_SUBTRACT, o_subtract); F_ALIAS(F_AND, o_and); F_ALIAS(F_OR, o_or); F_ALIAS(F_XOR, o_xor); F_ALIAS(F_MULTIPLY, o_multiply); F_ALIAS(F_DIVIDE, o_divide); F_ALIAS(F_MOD, o_mod); F_ALIAS(F_CAST, f_cast); F_ALIAS(F_CAST_TO_INT, o_cast_to_int); F_ALIAS(F_CAST_TO_STRING, o_cast_to_string); F_ALIAS(F_RANGE, o_range);
-
/* F_ZERO_TYPE? */
-
}
+
-
SPARC
_
FLUSH_UNSTORED
();
+
F
_
ALIAS(F
_
SSCANF, o_sscanf
);
-
{
-
static int last_prog_id=-1;
-
static size_t last_num_linenumbers=(size_t)~0;
-
if(last_prog_id != Pike_compiler->new_program->id ||
-
last_num_linenumbers != Pike_compiler->new_program->num_linenumbers)
-
{
-
last_prog_id=Pike_compiler->new_program->id;
-
last_num_linenumbers = Pike_compiler->new_program->num_linenumbers;
-
-
LOAD_PIKE_FP();
-
-
/*
Note: We fill the delay slot with the following opcode.
-
* This works since the new %o7 is available immediately.
-
* (Sparc Architecture Manual V9 p149.)
-
*/
-
-
/* stw %o7, [ %pike
_
fp, %offsetof(pike
_
frame,
pc) ]
*/
-
add_to_program(0xc0202000|(SPARC_REG_O7<<25)|(SPARC_REG_PIKE_FP<<14)|
-
OFFSETOF(pike_frame, pc));
-
-
delay_ok = 1;
+
/*
F
_
ZERO
_
TYPE?
*/
}
-
}
+
-
ADD
_
CALL
(addr, delay_ok);
-
-
/* This is probably only needed for some instructions, but... */
-
SPARC_UNLOAD_CACHED();
+
low
_
ins_call
(addr, delay_ok);
} void ins_f_byte(unsigned int opcode) { low_ins_f_byte(opcode, 0); } void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) {
-
+
#if 0
+
switch(a) {
+
case F_NUMBER:
+
sparc_push_int(b, 0);
+
return;
+
case F_NEG_NUMBER:
+
sparc_push_int(-b, 0);
+
return;
+
case F_LFUN:
+
sparc_push_lfun(b);
+
return;
+
case F_MARK_X:
+
sparc_mark(-b);
+
return;
+
}
+
#endif /* 0 */
SET_REG(SPARC_REG_O0, b); low_ins_f_byte(a, 1); return; } void ins_f_byte_with_2_args(unsigned int a, unsigned INT32 c, unsigned INT32 b) { SET_REG(SPARC_REG_O0, c);