File: make_mode.c

package info (click to toggle)
fis-gtm 7.1-006-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,908 kB
  • sloc: ansic: 344,906; asm: 5,184; csh: 4,859; sh: 2,000; awk: 294; makefile: 73; sed: 13
file content (219 lines) | stat: -rw-r--r-- 7,239 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/****************************************************************
 *								*
 * Copyright (c) 2001-2023 Fidelity National Information	*
 * Services, Inc. and/or its subsidiaries. All rights reserved.	*
 *								*
 *	This source code contains the intellectual property	*
 *	of its copyright holder(s), and is made available	*
 *	under a license.  If you do not know the terms of	*
 *	the license, please stop and do not read further.	*
 *								*
 ****************************************************************/

#include "mdef.h"

#include "gtm_string.h"

#include "error.h"
#include "dm_setup.h"
#include <rtnhdr.h>
#include "op.h"
#include "compiler.h"
#include <emit_code.h>
#include "gtmci.h"
#include "inst_flush.h"
#include "obj_file.h"
#include "gtm_text_alloc.h"

#ifdef USHBIN_SUPPORTED
/* From here down is only defined in a shared binary environment */

#include "make_mode.h"

#ifdef __ia64

#if defined(__linux__)

void dmode_table_init() __attribute__((constructor));

#else /* __hpux */

#pragma INIT "dmode_table_init"

#endif /* __linux__ */

void dmode_table_init(void);

#endif /* __ia64 */

/* This routine is called to create (currently two different) dynamic routines that
 * can be executed. One is a direct mode frame, the other is a callin base frame. They
 * are basically identical except in the entry points that they call. To this end, this
 * common routine is called for both with the entry points to be put into the generated
 * code being passed in as parameters.
 */
typedef struct dyn_modes_struct
{
	char 		*rtn_name;
	int		rtn_name_len;
	void		(*func_ptr1)(void);
	void		(*func_ptr2)(void);
	int		(*func_ptr3)(void);
} dyn_modes;

static dyn_modes our_modes[2] =
{
	{
		GTM_DMOD,
		SIZEOF(GTM_DMOD) - 1,
		dm_setup,
		mum_tstart,
		opp_ret
	},
	{
		GTM_CIMOD,
		SIZEOF(GTM_CIMOD) - 1,
		ci_restart,
		ci_ret_code,
		opp_ret
	}
};

#if defined(__ia64)

/* On IA64, we want to use CODE_ADDRESS() macro, to dereference all the function pointers, before storing them in
 * global array. Now doing a dereference operation, as part of initialization, is not allowed by linux/gcc (HP'a aCC
 * was more tolerant towards this). So to make sure that the xfer_table is initialized correctly, before anyone
 * uses it, one needs to create a 'constructor/initializer' function, which is gauranted to be called as soon as
 * this module is loaded, and initialize the xfer_table correctly within that function.  gcc provides the below
 * mechanism to do this
 */
static char dyn_modes_type[2][3] = {
					{'C','A','A'},
					{'A','C','A'}
};

void dmode_table_init()
{
	/*
	our_modes[0].func_ptr1 = (void (*)())CODE_ADDRESS(our_modes[0].func_ptr1);
	our_modes[0].func_ptr2 = (void (*)())CODE_ADDRESS(our_modes[0].func_ptr2);
	our_modes[0].func_ptr3 = (int (*)())CODE_ADDRESS(our_modes[0].func_ptr3);

	our_modes[1].func_ptr1 = (void (*)())CODE_ADDRESS(our_modes[1].func_ptr1);
	our_modes[1].func_ptr2 = (void (*)())CODE_ADDRESS(our_modes[1].func_ptr2);
	our_modes[1].func_ptr3 = (int (*)())CODE_ADDRESS(our_modes[1].func_ptr3);
	*/
}

#endif /* __ia64 */

rhdtyp *make_mode (int mode_index)
{
	rhdtyp		*base_address;
	lab_tabent	*lbl;
	lnr_tabent	*lnr;
	CODEBUF_TYPE	*code;
	dyn_modes	*dmode;
	int algnd_rtnhdr_size = (int)ROUND_UP2(SIZEOF(rhdtyp), SECTION_ALIGN_BOUNDARY);
	int algnd_code_size   = (int)ROUND_UP2(CODE_SIZE, NATIVE_WSIZE);
	int algnd_lbltab_size = (int)ROUND_UP2(SIZEOF(lab_tabent), NATIVE_WSIZE);
	int algnd_lnrtab_size = (int)ROUND_UP2(CODE_LINES * SIZEOF(lnr_tabent), NATIVE_WSIZE);

	/* Define some types since SCA sometimes doesn't like the way we use the memory past the header */
	typedef unsigned char rhd_bytes[algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size];
	typedef rhd_bytes *rhd_bytes_p;
	rhd_bytes_p bytes;

	assert((DM_MODE == mode_index) || (CI_MODE == mode_index));
        base_address = (rhdtyp *)GTM_TEXT_ALLOC(algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size);
	bytes = (rhd_bytes_p) base_address;	/* Treat our allocated memory as a sized array of bytes for SCA */
	memset(base_address, 0, algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size);
	dmode = &our_modes[mode_index];
	base_address->routine_name.len = dmode->rtn_name_len;
	base_address->routine_name.addr = dmode->rtn_name;
	base_address->ptext_adr = &((unsigned char *)bytes)[algnd_rtnhdr_size];
	base_address->ptext_end_adr = &((unsigned char *)bytes)[algnd_rtnhdr_size + algnd_code_size];
	base_address->lnrtab_adr = (lnr_tabent *)base_address->ptext_end_adr;
	base_address->labtab_adr = (lab_tabent *) &(((unsigned char *)bytes)[algnd_rtnhdr_size +
		algnd_code_size + algnd_lnrtab_size]);
	base_address->lnrtab_len = CODE_LINES;
	base_address->labtab_len = 1;
	code = (CODEBUF_TYPE *)base_address->ptext_adr;	/* start of executable code */
#ifdef __ia64
	if (dyn_modes_type[mode_index][0] == 'C')
	{
		GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr1))		/* line 0,1 */
	} else
	{
		GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr1))		/* line 0,1 */
	}
#else
	GEN_CALL(dmode->func_ptr1);			/* line 0,1 */
#endif /* __ia64 */

#ifdef _AIX
	if (CI_MODE == mode_index)
	{
		/* Following 2 instructions are generated to call the routine stored in GTM_REG_ACCUM.
		 * ci_restart would have loaded this register with the address of op_extcall/op_extexfun.
		 * On other platforms, ci_start usually invokes op_ext* which will return directly
		 * to the generated code. Since RS6000 doesn't support call instruction without altering
		 * return address register (LR), the workaround is to call op_ext* not from ci_restart
		 * but from this dummy code
		 */
		*code++ = RS6000_INS_MTLR | GTM_REG_ACCUM << RS6000_SHIFT_RS;
		*code++ = RS6000_INS_BRL;
	}
#endif

#ifdef __ia64
        if (dyn_modes_type[mode_index][1] == 'C')
	{
                GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr2))
	} else
	{
                GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr2))
	}
#else
        GEN_CALL(dmode->func_ptr2);
#endif /* __ia64 */

#if defined (__ia64)
	if (DM_MODE == mode_index)
	{
		GEN_UNCOD_JUMP(-(2 * 5)); /* branch to dm_setup which is at the top of the direct mode frame. */
	}
#elif defined(__hpux)
	if (DM_MODE == mode_index)
	{
		*code++ = HPPA_INS_BEQ | (MAKE_COND_BRANCH_TARGET(-8) << HPPA_SHIFT_OFFSET); /* BEQ r0,r0, -8 */
		*code++ = HPPA_INS_NOP;
	}
#endif /* __ia64 */

#ifdef __ia64
        if (dyn_modes_type[mode_index][2] == 'C')
	{
                GEN_CALL_C(CODE_ADDRESS(dmode->func_ptr3));  	/* line 2 */
	} else
	{
                GEN_CALL_ASM(CODE_ADDRESS(dmode->func_ptr3));  /* line 2 */
	}
#else
        GEN_CALL(dmode->func_ptr3); 			/* line 2 */
#endif /* __ia64 */
	lnr = LNRTAB_ADR(base_address);
	*lnr++ = 0;								/* line 0 */
	*lnr++ = 0;								/* line 1 */
	IA64_ONLY(*lnr++ = 2 * CALL_SIZE + EXTRA_INST_SIZE;)			/* line 2 */
	NON_IA64_ONLY(*lnr++ = 2 * CALL_SIZE + EXTRA_INST * SIZEOF(int);)	/* line 2 */
	lbl = base_address->labtab_adr;
	lbl->lnr_adr = base_address->lnrtab_adr;
	base_address->current_rhead_adr = base_address;
	zlput_rname(base_address);
	inst_flush(base_address, algnd_rtnhdr_size + algnd_code_size + algnd_lbltab_size + algnd_lnrtab_size);
	return base_address;
}

#endif /* USHBIN_SUPPORTED */