Return non-zero if an error occurs.
[AROS.git] / tools / sfdc / StubMOS.pl
blob9763d59f2da365f6eb5c6b628571c223ed7609b2
2 ### Class StubMOS: Create a MorphOS stub file #################################
4 BEGIN {
5 package StubMOS;
6 use vars qw(@ISA);
7 @ISA = qw( Stub );
9 sub new {
10 my $proto = shift;
11 my $class = ref($proto) || $proto;
12 my $self = $class->SUPER::new( @_ );
13 bless ($self, $class);
14 return $self;
17 sub header {
18 my $self = shift;
20 $self->SUPER::header (@_);
22 print "\n";
23 print "#include <emul/emulregs.h>\n";
24 print "#include <stdarg.h>\n";
25 print "\n";
28 sub function_proto {
29 my $self = shift;
30 my %params = @_;
31 my $prototype = $params{'prototype'};
33 if ($prototype->{type} eq 'varargs') {
35 if ($prototype->{subtype} ne 'tagcall') {
36 # We have to add the attribute to ourself first
38 $self->special_function_proto (@_);
39 print " __attribute__((varargs68k));\n";
40 print "\n";
41 $self->special_function_proto (@_);
44 else {
45 $self->SUPER::function_proto (@_);
49 sub function_start {
50 my $self = shift;
51 my %params = @_;
52 my $prototype = $params{'prototype'};
53 my $sfd = $self->{SFD};
55 if ($prototype->{type} eq 'function') {
56 print "\n";
57 print "{\n";
59 if (!$prototype->{nb}) {
60 print " BASE_EXT_DECL\n";
63 elsif ($prototype->{type} eq 'varargs') {
64 if ($prototype->{subtype} ne 'tagcall') {
65 my $na;
67 if ($prototype->{subtype} eq 'printfcall') {
68 $na = $prototype->{numargs} - 2;
70 else {
71 # methodcall: first vararg is removed
72 $na = $prototype->{numargs} - 3;
75 print "\n";
76 print "{\n";
77 print " va_list _va;\n";
78 print " va_start (_va, $prototype->{___argnames}[$na]);\n";
79 print " return $$prototype{'real_funcname'}(BASE_PAR_NAME ";
81 else {
82 # Shamelessly stolen from fd2inline ...
84 # number of regs that contain varargs
85 my $n = 9 - $prototype->{numregs};
87 # add 4 bytes if that's an odd number, to avoid splitting a tag
88 my $d = $n & 1 ? 4 : 0;
90 # offset of the start of the taglist
91 my $taglist = 8;
93 # size of the stack frame
94 my $local = ($taglist + $n * 4 + $d + 8 + 15) & ~15;
96 # Stack frame:
98 # 0 - 3: next frame ptr
99 # 4 - 7: save lr
100 # 8 - 8+n*4+d+8-1: tag list start
101 # ? - local-1: padding
103 print "__asm(\"\n";
104 print " .align 2\n";
105 print " .globl $prototype->{funcname}\n";
106 print " .type $prototype->{funcname},\@function\n";
107 print "$prototype->{funcname}:\n";
108 print " stwu 1,-$local(1)\n";
109 print " mflr 0\n";
110 printf " stw 0,%d(1)\n", $local + 4;
112 # If n is odd, one tag is split between regs and stack.
113 # Copy its ti_Data together with the ti_Tag.
115 if ($d != 0) {
116 # read ti_Data
117 printf " lwz 0,%d(1)\n", $local + 8;
120 # Save the registers
122 for my $count ($prototype->{numregs} .. 8) {
123 printf " stw %d,%d(1)\n",
124 $count + 2,
125 ($count - $prototype->{numregs}) * 4 + $taglist;
128 if ($d != 0) {
129 # write ti_Data
130 printf " stw 0,%d(1)\n", $taglist + $n * 4;
133 # Add TAG_MORE
135 print " li 11,2\n";
136 printf " addi 0,1,%d\n", $local + 8 + $d;
137 printf " stw 11,%d(1)\n", $taglist + $n * 4 + $d;
138 printf " stw 0,%d(1)\n", $taglist + $n * 4 + $d + 4;
140 # vararg_reg = &saved regs
142 printf " addi %d,1,%d\n",
143 $prototype->{numregs} + 2, $taglist;
144 print " bl $prototype->{real_funcname}\n";
147 else {
148 $self->SUPER::function_start (@_);
152 sub function_arg {
153 my $self = shift;
154 my %params = @_;
155 my $prototype = $params{'prototype'};
156 my $argtype = $params{'argtype'};
157 my $argname = $params{'argname'};
158 my $argreg = $params{'argreg'};
159 my $argnum = $params{'argnum'};
160 my $sfd = $self->{SFD};
162 if ($$prototype{'type'} eq 'function') {
163 print " REG_" . (uc $argreg) . " = (ULONG) $argname;\n";
165 elsif ($prototype->{type} eq 'varargs') {
166 if ($prototype->{subtype} eq 'tagcall') {
167 # if ($argnum < $prototype->{numargs} - 2) {
168 # my $regoffset;
170 # if ($argreg =~ /^d[0-9]$/) {
171 # ( $regoffset = $argreg ) =~ s/^d//;
173 # elsif ($argreg =~ /^a[0-9]$/) {
174 # ( $regoffset = $argreg ) =~ s/^a//;
175 # $regoffset += 8;
177 # else {
178 # die;
181 # $regoffset *= 4;
183 # # Save the non-varargs registers in the EmulHandle struct
185 # printf " stw %d,%d(2)\n", $argnum + 3, $regoffset;
188 elsif ($prototype->{subtype} eq 'methodcall' &&
189 $argnum == $prototype->{numargs} - 2) {
190 # Nuke it!
192 elsif ($argnum == $prototype->{numargs} - 1) {
193 my $vt = $$prototype{'argtypes'}[$$prototype{'numargs'} - 1];
194 print ", ($vt) _va->overflow_arg_area";
196 else {
197 $self->SUPER::function_arg (@_);
200 else {
201 $self->SUPER::function_arg (@_);
205 sub function_end {
206 my $self = shift;
207 my %params = @_;
208 my $prototype = $params{'prototype'};
209 my $sfd = $self->{SFD};
212 if ($$prototype{'type'} eq 'function') {
213 if (!$prototype->{nb}) {
214 print " REG_A6 = (ULONG) BASE_NAME;\n";
217 print " ";
219 if (!$prototype->{nr}) {
220 print "return ($prototype->{return}) ";
223 print "(*MyEmulHandle->EmulCallDirectOS)(-$prototype->{bias});\n";
224 print "}\n";
226 elsif ($prototype->{type} eq 'varargs') {
227 if ($prototype->{subtype} eq 'tagcall') {
228 # number of regs that contain varargs
229 my $n = 9 - $prototype->{numregs};
231 # add 4 bytes if that's an odd number, to avoid splitting a tag
232 my $d = $n & 1 ? 4 : 0;
234 # offset of the start of the taglist
235 my $taglist = 8;
237 # size of the stack frame
238 my $local = ($taglist + $n * 4 + $d + 8 + 15) & ~15;
240 # clear stack frame & return
241 printf " lwz 0,%d(1)\n", $local + 4;
242 print " mtlr 0\n";
243 printf " addi 1,1,%d\n", $local;
244 print " blr\n";
245 print ".L$prototype->{funcname}e1:\n";
246 print " .size $prototype->{funcname}," .
247 ".L$prototype->{funcname}e1-$prototype->{funcname}\n";
249 print "\");\n";
251 else {
252 print ");\n";
253 print "}\n";
256 else {
257 $self->SUPER::function_end (@_);
262 sub special_function_proto {
263 my $self = shift;
264 my %params = @_;
265 my $prototype = $params{'prototype'};
266 my $decl_regular = $params{'decl_regular'};
267 my $sfd = $self->{SFD};
269 if ($prototype->{type} eq 'varargs' && $decl_regular) {
270 my $rproto = $prototype->{real_prototype};
272 print "$$rproto{'return'} $$rproto{'funcname'}(";
273 if (!$prototype->{nb}) {
274 if ($$rproto{'numargs'} == 0) {
275 print "BASE_PAR_DECL0";
277 else {
278 print "BASE_PAR_DECL ";
281 print join (', ', @{$$rproto{'___args'}});
283 print ");\n";
284 print "\n";
287 print "$$prototype{'return'}\n";
288 print "$$prototype{'funcname'}(";
289 if (!$prototype->{nb}) {
290 if ($$prototype{'numargs'} == 0) {
291 print "BASE_PAR_DECL0";
293 else {
294 print "BASE_PAR_DECL ";
298 my @newargs;
300 for my $i (0 .. $#{@{$prototype->{___args}}}) {
301 if ($prototype->{subtype} ne 'methodcall' ||
302 $i != $prototype->{numargs} - 2 ) {
303 push @newargs, $prototype->{___args}[$i];
307 print join (', ', @newargs);
308 print ")";