-
Notifications
You must be signed in to change notification settings - Fork 0
/
speedcode.c
219 lines (173 loc) · 8.71 KB
/
speedcode.c
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
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include "speedcode.h"
#include "speedcode_Internal.h"
#include <mem\mem.h>
/*CC65 Bug: &nameofstruct != nameofstruct
void (*dest)(void), ++dest increases dest by 2 instead of one!*/
/* Smallest Size: 0x1bd, 0x1ba, 0x1c1*/
//#define spcode_def_loc spdcdef_and_counters.spdcdef_loc
//spcode_spec spcode_def_loc;
spcode_SpecAndState_t spcode_def_loc;
spcode_PartSpec_t spdcpartdef_loc;
//The memory seems to be allocated wrongly
//ptrdiff_t counter_offset;
// Offset between storage area of maxima and counters
spcode_t *spcode_StoreDest;
spcode_t* __fastcall__ spcode_SetDestination(spcode_t *dest)
{
spcode_StoreDest = dest;
return spcode_StoreDest;
}
//***********************************************************************************
//Replicate the small piece of assembler code and modify the code after each copy
//***********************************************************************************
void __fastcall__ spcode_CopyPart(register spcode_PartSpec_t *spcode_partdef)
{
//static spcode_PartSpec_t *oldspec = NULL;
dprintf("-- Called \"spcode_CopyPart\", &Partspec=%x --\n", spcode_partdef);
//Optimization could be to copy only necessary information like pointer to assembly and size
//Use local pointer var i instead of spcode_def_loc.Counters.PartRepeat
//if (oldspec != spcode_partdef)
//COPY_SPEEDCODEPART_SPEC(*spcode_partdef, spdcpartdef_loc);
spdcpartdef_loc = *spcode_partdef;
//not needed anymore. is handled by own asm call code
//if(NULL == spdcpartdef_loc.Callback){spdcpartdef_loc.Callback = (void*)&rts;}
assert( 0 == memcmp ( spcode_partdef, &spdcpartdef_loc, sizeof(spcode_PartSpec_t) ) );
//Assert that the struct spcode_partdef is correctly copied to the local representation
spcode_def_loc.Counters.PartRepeat = spcode_def_loc.Limits.PartRepeat = spdcpartdef_loc.Repeats;
assert ( 0 == spcode_GetCounter(SPCODE_PARTREPEAT_IDX) );
//GetCounter must return zero for the startvalue of the counter
if (NULL != spdcpartdef_loc.Setup) spdcpartdef_loc.Setup(spdcpartdef_loc.Parameters);
setCallbackJmpAddr(spdcpartdef_loc.Callback);
for( ;spcode_def_loc.Counters.PartRepeat > 0; --spcode_def_loc.Counters.PartRepeat )
/*To avoid side effects using this loop function with recursive functions, the comparison and the incrementation are not
bundled together in one command*/
{
dprintf(" Iteration:%d, Counter:%d\n", spcode_def_loc.Counters.PartRepeat-1, spcode_GetCounter(SPCODE_PARTREPEAT_IDX));
//if(spdcpartdef_loc.callback){spdcpartdef_loc.callback(spdcpartdef_loc.parameters);}
//(unsigned char*)storedest = (unsigned char*)memcpy(storedest, spdcpartdef_loc.assembly_code, spdcpartdef_loc.size)+spdcpartdef_loc.size;
//copycode();
//dprintf(" Partrepeatcount: %d\n", spcode_def_loc.repeat.part);
//Secure, because pointer to rts is written if function pointer is NULL
//spdcpartdef_loc.Callback(spdcpartdef_loc.Parameters);
fastCallback(spdcpartdef_loc.Parameters);
//(unsigned char*)spcode_StoreDest = (unsigned char*)memcpy256(spdcpartdef_loc.Size, spdcpartdef_loc.AssemblyCode, spcode_StoreDest);
(unsigned char*)spcode_StoreDest = (unsigned char*)fastmemcpy256(spdcpartdef_loc.Size, spdcpartdef_loc.AssemblyCode, spcode_StoreDest);
//spcode_Add (spdcpartdef_loc.AssemblyCode, spdcpartdef_loc.Size);
//Inner Loop Counter works ok, if spcode_Add is not called. Something interferes!
}
if (NULL != spdcpartdef_loc.Teardown) spdcpartdef_loc.Setup(spdcpartdef_loc.Teardown);
}
//***********************************************************************************
//Run the loops for the replication and call routine for copying the assembly code
//***********************************************************************************
void __fastcall__ spcode_Replicate(register spcode_Iterator_t *indexarr)
{
//register unsigned int *indexarr = index;
//The partindex of the indexarray must be specified
//Maximum and running values have constant offset in structure. so calculate pointer to max value
//from pointer to running value
spcode_Iterator_t *max = (spcode_Iterator_t*)(
(uint8_t*)indexarr -
( offsetof(spcode_SpecAndState_t, Counters) -
offsetof(spcode_SpecAndState_t, Limits) )
);
//Output debug information about the call and the recursion level
dprintf("## Called \"create_loop\" with level:%d ##\n",
(max-(spcode_Iterator_t*)&spcode_def_loc.Limits)
);
if ( indexarr <= &spcode_def_loc.Counters.Part )
{
//unsigned int max_loc = *max;
// no NULL Pointer acceptable, pointer not outside reserved memspace
assert( max >= (spcode_Iterator_t*)(&spcode_def_loc.Limits) );
assert( max <= (spcode_Iterator_t*)(&spcode_def_loc.Limits + 1) );
// no NULL Pointer acceptable, pointer not outside reserved memspace
assert( indexarr >= &spcode_def_loc.Counters.arr[0] );
assert( indexarr <= ( &spcode_def_loc.Counters.arr[SPCODE_NUMOFLOOPS-1] ) );
dprintf("Max:%d, &Max:%x, &Last Index:%x, \n", *max, max, &spcode_def_loc.Limits.Part);
#ifndef NDEBUG
*indexarr = *max;
assert ( 0 == spcode_GetCounter(indexarr-(spcode_Iterator_t*)&spcode_def_loc.Counters) );
#endif
//GetCounter must return a zero value for the value of the index before the loop starts
for ( *indexarr = *max;
(*indexarr) > 0;
--(*indexarr)
)
//To avoid side effects using this loop function with recursive functions, the comparison and the incrementation are not
//bundled together in one command
{
dprintf(" Iterat.:%d, &index:%x, Counter: %d\n", *indexarr, indexarr,
spcode_GetCounter(
(indexarr-(spcode_Iterator_t*)&spcode_def_loc.Counters)
)
);
spcode_Replicate(indexarr+1/*(unsigned int*)((unsigned char*)max+
( (unsigned char*)offsetof(spcode_def_counters_t, counters)-
(unsigned char*)offsetof(spcode_def_counters_t, repeat) ))*/
);
}
}else
{
spcode_CopyPart(spcode_def_loc.PartSpec);
//Pass the pointer to the partdefinition in the same row as given by the main program
//Starting with index zero. Remember, loops run backwards
}
dprintf("...Leaving level:%d\n", ( max-(spcode_Iterator_t*)&spcode_def_loc.Limits ) );
}
//***********************************************************************************
//Initialize the speedcode replication routine
//***********************************************************************************
spcode_t* __fastcall__ spcode_Create(spcode_Spec_t* spdcdef, spcode_t *dest)
{
//Output debug information, that create_spcode was called
dprintf("********************************\n"
"Called \"create_spcode\" with\n"
"&def = %x, &counters = %x\n"
"********************************\n", spdcdef, dest);
//*****************************************
//Assert valid content of spdcdef structure
//*****************************************
//Assert that pointer to spcode_part specifications is not NULL
assert( (spdcdef -> PartSpec) > 0);
//Assert number of repeats for all indexes beeing so that total repeats r.x*r.y*r.z*r.part does not multiply to 0
//assert( (spdcdef -> Limits.x) > 0);
//assert( (spdcdef -> Limits.y) > 0);
//assert( (spdcdef -> Limits.z) > 0);
//assert( (spdcdef -> Limits.Part) > 0);
//************************************************
//If no address for dest is given, allocate memory
//************************************************
if (!dest)// Explicit assignment, = operator is right here!!!
//It seems to generate more effective code testing against a variable being not zero and move the code for the zero result
//outside the if block
{
dest = malloc(spcode_CalcSize(spdcdef));
//dest is not used anymore from now on!
}
//memcpy256( sizeof(spcode_def_loc), spdcdef, &spcode_def_loc );
spcode_StoreDest = dest;
//Make local copy of spcode definitions for faster access to struct elements
spcode_def_loc.Spec = *spdcdef;
//Calculate offset between index and maxima array, needed in spcode_create_loop(...
//counter_offset = (uint8_t*)counters - (uint8_t*)&spcode_def_loc.repeat.z;
if (NULL != spcode_def_loc.Spec.Setup) spcode_def_loc.Spec.Setup(NULL);
//Start recursive procedure for spcode generation
spcode_Replicate(
//&spcode_def_loc.repeat.z,
//&(counters->arr[0])
&spcode_def_loc.Counters.arr[0]
);
/*memcpy returns the destination address. As the address of spdcdef_loc, which is the destination, and the
address of the array with the repeat limits are equal, the return value of memcpy can be passed through*/
*(unsigned char*)spcode_StoreDest=RTS;
if (NULL != spcode_def_loc.Spec.Teardown) spcode_def_loc.Spec.Teardown(NULL);
return dest;
}