• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


コミットメタ情報

リビジョンb7718b973cefe74b3bdc221351145f657306e326 (tree)
日時2009-07-10 14:00:24
作者Jack Palevich <jackpal@goog...>
コミッターJack Palevich

ログメッセージ

Implement floating point for ARM.

変更サマリ

差分

--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -270,7 +270,7 @@ class Compiler : public ErrorSink {
270270 }
271271
272272 /* Emit a function prolog.
273- * argCount is the number of arguments.
273+ * pDecl is the function declaration, which gives the arguments.
274274 * Save the old value of the FP.
275275 * Set the new value of the FP.
276276 * Convert from the native platform calling convention to
@@ -282,7 +282,7 @@ class Compiler : public ErrorSink {
282282 * functionExit().
283283 * returns address to patch with local variable size.
284284 */
285- virtual int functionEntry(int argCount) = 0;
285+ virtual int functionEntry(Type* pDecl) = 0;
286286
287287 /* Emit a function epilog.
288288 * Restore the old SP and FP register values.
@@ -291,7 +291,7 @@ class Compiler : public ErrorSink {
291291 * localVariableAddress - returned from functionEntry()
292292 * localVariableSize - the size in bytes of the local variables.
293293 */
294- virtual void functionExit(int argCount, int localVariableAddress,
294+ virtual void functionExit(Type* pDecl, int localVariableAddress,
295295 int localVariableSize) = 0;
296296
297297 /* load immediate value to R0 */
@@ -398,7 +398,7 @@ class Compiler : public ErrorSink {
398398 * On ARM for example you would pop the first 5 arguments into
399399 * R0..R4
400400 */
401- virtual void endFunctionCallArguments(int a, int l) = 0;
401+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) = 0;
402402
403403 /* Emit a call to an unknown function. The argument "symbol" needs to
404404 * be stored in the location where the address should go. It forms
@@ -424,7 +424,7 @@ class Compiler : public ErrorSink {
424424 * is true if this was an indirect call. (In which case the
425425 * address of the function is stored at location SP + l.)
426426 */
427- virtual void adjustStackAfterCall(int l, bool isIndirect) = 0;
427+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0;
428428
429429 /* Print a disassembly of the assembled code to out. Return
430430 * non-zero if there is an error.
@@ -452,7 +452,7 @@ class Compiler : public ErrorSink {
452452 /**
453453 * Memory alignment (in bytes) for this type of data
454454 */
455- virtual size_t alignment(Type* type) = 0;
455+ virtual size_t alignmentOf(Type* type) = 0;
456456
457457 /**
458458 * Array element alignment (in bytes) for this type of data.
@@ -561,15 +561,15 @@ class Compiler : public ErrorSink {
561561
562562 /* returns address to patch with local variable size
563563 */
564- virtual int functionEntry(int argCount) {
565- LOG_API("functionEntry(%d);\n", argCount);
564+ virtual int functionEntry(Type* pDecl) {
565+ LOG_API("functionEntry(%d);\n", pDecl);
566566 mStackUse = 0;
567567 // sp -> arg4 arg5 ...
568568 // Push our register-based arguments back on the stack
569- if (argCount > 0) {
570- int regArgCount = argCount <= 4 ? argCount : 4;
571- o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {}
569+ int regArgCount = calcRegArgCount(pDecl);
570+ if (regArgCount > 0) {
572571 mStackUse += regArgCount * 4;
572+ o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd sp!, {}
573573 }
574574 // sp -> arg0 arg1 ...
575575 o4(0xE92D4800); // stmfd sp!, {fp, lr}
@@ -583,7 +583,7 @@ class Compiler : public ErrorSink {
583583 // STACK_ALIGNMENT, so it won't affect the stack alignment.
584584 }
585585
586- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
586+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
587587 LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
588588 // Round local variable size up to a multiple of stack alignment
589589 localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) /
@@ -601,12 +601,13 @@ class Compiler : public ErrorSink {
601601 // sp -> retadr, arg0, ...
602602 o4(0xE8BD4000); // ldmfd sp!, {lr}
603603 // sp -> arg0 ....
604- if (argCount > 0) {
605- // We store the PC into the lr so we can adjust the sp before
606- // returning. We need to pull off the registers we pushed
607- // earlier. We don't need to actually store them anywhere,
608- // just adjust the stack.
609- int regArgCount = argCount <= 4 ? argCount : 4;
604+
605+ // We store the PC into the lr so we can adjust the sp before
606+ // returning. We need to pull off the registers we pushed
607+ // earlier. We don't need to actually store them anywhere,
608+ // just adjust the stack.
609+ int regArgCount = calcRegArgCount(pDecl);
610+ if (regArgCount) {
610611 o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2
611612 }
612613 o4(0xE12FFF1E); // bx lr
@@ -630,8 +631,24 @@ class Compiler : public ErrorSink {
630631 }
631632
632633 virtual void loadFloat(int address, Type* pType) {
633- error("Unimplemented.\n");
634634 setR0Type(pType);
635+ // Global, absolute address
636+ o4(0xE59F0000); // ldr r0, .L1
637+ o4(0xEA000000); // b .L99
638+ o4(address); // .L1: .word ea
639+ // .L99:
640+
641+ switch (pType->tag) {
642+ case TY_FLOAT:
643+ o4(0xE5900000); // ldr r0, [r0]
644+ break;
645+ case TY_DOUBLE:
646+ o4(0xE1C000D0); // ldrd r0, [r0]
647+ break;
648+ default:
649+ assert(false);
650+ break;
651+ }
635652 }
636653
637654 virtual int gjmp(int t) {
@@ -642,6 +659,18 @@ class Compiler : public ErrorSink {
642659 /* l = 0: je, l == 1: jne */
643660 virtual int gtst(bool l, int t) {
644661 LOG_API("gtst(%d, %d);\n", l, t);
662+ Type* pR0Type = getR0Type();
663+ TypeTag tagR0 = pR0Type->tag;
664+ switch(tagR0) {
665+ case TY_FLOAT:
666+ callRuntime((void*) runtime_is_non_zero_f);
667+ break;
668+ case TY_DOUBLE:
669+ callRuntime((void*) runtime_is_non_zero_d);
670+ break;
671+ default:
672+ break;
673+ }
645674 o4(0xE3500000); // cmp r0,#0
646675 int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
647676 return o4(branch | encodeAddress(t));
@@ -649,122 +678,273 @@ class Compiler : public ErrorSink {
649678
650679 virtual void gcmp(int op, Type* pResultType) {
651680 LOG_API("gcmp(%d);\n", op);
652- o4(0xE8BD0002); // ldmfd sp!,{r1}
653- mStackUse -= 4;
654- o4(0xE1510000); // cmp r1, r1
655- switch(op) {
656- case OP_EQUALS:
657- o4(0x03A00001); // moveq r0,#1
658- o4(0x13A00000); // movne r0,#0
659- break;
660- case OP_NOT_EQUALS:
661- o4(0x03A00000); // moveq r0,#0
662- o4(0x13A00001); // movne r0,#1
663- break;
664- case OP_LESS_EQUAL:
665- o4(0xD3A00001); // movle r0,#1
666- o4(0xC3A00000); // movgt r0,#0
667- break;
668- case OP_GREATER:
669- o4(0xD3A00000); // movle r0,#0
670- o4(0xC3A00001); // movgt r0,#1
671- break;
672- case OP_GREATER_EQUAL:
673- o4(0xA3A00001); // movge r0,#1
674- o4(0xB3A00000); // movlt r0,#0
675- break;
676- case OP_LESS:
677- o4(0xA3A00000); // movge r0,#0
678- o4(0xB3A00001); // movlt r0,#1
679- break;
680- default:
681- error("Unknown comparison op %d", op);
682- break;
681+ Type* pR0Type = getR0Type();
682+ Type* pTOSType = getTOSType();
683+ TypeTag tagR0 = collapseType(pR0Type->tag);
684+ TypeTag tagTOS = collapseType(pTOSType->tag);
685+ if (tagR0 == TY_INT && tagTOS == TY_INT) {
686+ o4(0xE8BD0002); // ldmfd sp!,{r1}
687+ mStackUse -= 4;
688+ o4(0xE1510000); // cmp r1, r1
689+ switch(op) {
690+ case OP_EQUALS:
691+ o4(0x03A00001); // moveq r0,#1
692+ o4(0x13A00000); // movne r0,#0
693+ break;
694+ case OP_NOT_EQUALS:
695+ o4(0x03A00000); // moveq r0,#0
696+ o4(0x13A00001); // movne r0,#1
697+ break;
698+ case OP_LESS_EQUAL:
699+ o4(0xD3A00001); // movle r0,#1
700+ o4(0xC3A00000); // movgt r0,#0
701+ break;
702+ case OP_GREATER:
703+ o4(0xD3A00000); // movle r0,#0
704+ o4(0xC3A00001); // movgt r0,#1
705+ break;
706+ case OP_GREATER_EQUAL:
707+ o4(0xA3A00001); // movge r0,#1
708+ o4(0xB3A00000); // movlt r0,#0
709+ break;
710+ case OP_LESS:
711+ o4(0xA3A00000); // movge r0,#0
712+ o4(0xB3A00001); // movlt r0,#1
713+ break;
714+ default:
715+ error("Unknown comparison op %d", op);
716+ break;
717+ }
718+ popType();
719+ } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) {
720+ setupDoubleArgs();
721+ switch(op) {
722+ case OP_EQUALS:
723+ callRuntime((void*) runtime_cmp_eq_dd);
724+ break;
725+ case OP_NOT_EQUALS:
726+ callRuntime((void*) runtime_cmp_ne_dd);
727+ break;
728+ case OP_LESS_EQUAL:
729+ callRuntime((void*) runtime_cmp_le_dd);
730+ break;
731+ case OP_GREATER:
732+ callRuntime((void*) runtime_cmp_gt_dd);
733+ break;
734+ case OP_GREATER_EQUAL:
735+ callRuntime((void*) runtime_cmp_ge_dd);
736+ break;
737+ case OP_LESS:
738+ callRuntime((void*) runtime_cmp_lt_dd);
739+ break;
740+ default:
741+ error("Unknown comparison op %d", op);
742+ break;
743+ }
744+ } else {
745+ setupFloatArgs();
746+ switch(op) {
747+ case OP_EQUALS:
748+ callRuntime((void*) runtime_cmp_eq_ff);
749+ break;
750+ case OP_NOT_EQUALS:
751+ callRuntime((void*) runtime_cmp_ne_ff);
752+ break;
753+ case OP_LESS_EQUAL:
754+ callRuntime((void*) runtime_cmp_le_ff);
755+ break;
756+ case OP_GREATER:
757+ callRuntime((void*) runtime_cmp_gt_ff);
758+ break;
759+ case OP_GREATER_EQUAL:
760+ callRuntime((void*) runtime_cmp_ge_ff);
761+ break;
762+ case OP_LESS:
763+ callRuntime((void*) runtime_cmp_lt_ff);
764+ break;
765+ default:
766+ error("Unknown comparison op %d", op);
767+ break;
768+ }
683769 }
684- popType();
770+ setR0Type(pResultType);
685771 }
686772
687773 virtual void genOp(int op) {
688774 LOG_API("genOp(%d);\n", op);
689- o4(0xE8BD0002); // ldmfd sp!,{r1}
690- mStackUse -= 4;
691- switch(op) {
692- case OP_MUL:
693- o4(0x0E0000091); // mul r0,r1,r0
694- break;
695- case OP_DIV:
696- callRuntime(runtime_DIV);
697- break;
698- case OP_MOD:
699- callRuntime(runtime_MOD);
700- break;
701- case OP_PLUS:
702- o4(0xE0810000); // add r0,r1,r0
703- break;
704- case OP_MINUS:
705- o4(0xE0410000); // sub r0,r1,r0
706- break;
707- case OP_SHIFT_LEFT:
708- o4(0xE1A00011); // lsl r0,r1,r0
709- break;
710- case OP_SHIFT_RIGHT:
711- o4(0xE1A00051); // asr r0,r1,r0
712- break;
713- case OP_BIT_AND:
714- o4(0xE0010000); // and r0,r1,r0
715- break;
716- case OP_BIT_XOR:
717- o4(0xE0210000); // eor r0,r1,r0
718- break;
719- case OP_BIT_OR:
720- o4(0xE1810000); // orr r0,r1,r0
721- break;
722- case OP_BIT_NOT:
723- o4(0xE1E00000); // mvn r0, r0
724- break;
725- default:
726- error("Unimplemented op %d\n", op);
727- break;
775+ Type* pR0Type = getR0Type();
776+ Type* pTOSType = getTOSType();
777+ TypeTag tagR0 = collapseType(pR0Type->tag);
778+ TypeTag tagTOS = collapseType(pTOSType->tag);
779+ if (tagR0 == TY_INT && tagTOS == TY_INT) {
780+ o4(0xE8BD0002); // ldmfd sp!,{r1}
781+ mStackUse -= 4;
782+ switch(op) {
783+ case OP_MUL:
784+ o4(0x0E0000091); // mul r0,r1,r0
785+ break;
786+ case OP_DIV:
787+ callRuntime((void*) runtime_DIV);
788+ break;
789+ case OP_MOD:
790+ callRuntime((void*) runtime_MOD);
791+ break;
792+ case OP_PLUS:
793+ o4(0xE0810000); // add r0,r1,r0
794+ break;
795+ case OP_MINUS:
796+ o4(0xE0410000); // sub r0,r1,r0
797+ break;
798+ case OP_SHIFT_LEFT:
799+ o4(0xE1A00011); // lsl r0,r1,r0
800+ break;
801+ case OP_SHIFT_RIGHT:
802+ o4(0xE1A00051); // asr r0,r1,r0
803+ break;
804+ case OP_BIT_AND:
805+ o4(0xE0010000); // and r0,r1,r0
806+ break;
807+ case OP_BIT_XOR:
808+ o4(0xE0210000); // eor r0,r1,r0
809+ break;
810+ case OP_BIT_OR:
811+ o4(0xE1810000); // orr r0,r1,r0
812+ break;
813+ case OP_BIT_NOT:
814+ o4(0xE1E00000); // mvn r0, r0
815+ break;
816+ default:
817+ error("Unimplemented op %d\n", op);
818+ break;
819+ }
820+ popType();
821+ } else {
822+ Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
823+ if (pResultType->tag == TY_DOUBLE) {
824+ setupDoubleArgs();
825+ switch(op) {
826+ case OP_MUL:
827+ callRuntime((void*) runtime_op_mul_dd);
828+ break;
829+ case OP_DIV:
830+ callRuntime((void*) runtime_op_div_dd);
831+ break;
832+ case OP_PLUS:
833+ callRuntime((void*) runtime_op_add_dd);
834+ break;
835+ case OP_MINUS:
836+ callRuntime((void*) runtime_op_sub_dd);
837+ break;
838+ default:
839+ error("Unsupported binary floating operation %d\n", op);
840+ break;
841+ }
842+ } else {
843+ setupFloatArgs();
844+ switch(op) {
845+ case OP_MUL:
846+ callRuntime((void*) runtime_op_mul_ff);
847+ break;
848+ case OP_DIV:
849+ callRuntime((void*) runtime_op_div_ff);
850+ break;
851+ case OP_PLUS:
852+ callRuntime((void*) runtime_op_add_ff);
853+ break;
854+ case OP_MINUS:
855+ callRuntime((void*) runtime_op_sub_ff);
856+ break;
857+ default:
858+ error("Unsupported binary floating operation %d\n", op);
859+ break;
860+ }
861+ }
862+ setR0Type(pResultType);
728863 }
729- popType();
730864 }
731865
732866 virtual void gUnaryCmp(int op, Type* pResultType) {
733867 LOG_API("gUnaryCmp(%d);\n", op);
734- o4(0xE3A01000); // mov r1, #0
735- o4(0xE1510000); // cmp r1, r1
736- switch(op) {
737- case OP_LOGICAL_NOT:
738- o4(0x03A00000); // moveq r0,#0
739- o4(0x13A00001); // movne r0,#1
740- break;
741- default:
742- error("Unknown unary comparison op %d", op);
743- break;
868+ if (op != OP_LOGICAL_NOT) {
869+ error("Unknown unary cmp %d", op);
870+ } else {
871+ Type* pR0Type = getR0Type();
872+ TypeTag tag = collapseType(pR0Type->tag);
873+ switch(tag) {
874+ case TY_INT:
875+ o4(0xE3A01000); // mov r1, #0
876+ o4(0xE1510000); // cmp r1, r1
877+ o4(0x03A00000); // moveq r0,#0
878+ o4(0x13A00001); // movne r0,#1
879+ break;
880+ case TY_FLOAT:
881+ callRuntime((void*) runtime_is_zero_f);
882+ break;
883+ case TY_DOUBLE:
884+ callRuntime((void*) runtime_is_zero_d);
885+ break;
886+ default:
887+ error("gUnaryCmp unsupported type");
888+ break;
889+ }
744890 }
745891 setR0Type(pResultType);
746892 }
747893
748894 virtual void genUnaryOp(int op) {
749895 LOG_API("genOp(%d);\n", op);
750- switch(op) {
751- case OP_MINUS:
752- o4(0xE3A01000); // mov r1, #0
753- o4(0xE0410000); // sub r0,r1,r0
754- break;
755- case OP_BIT_NOT:
756- o4(0xE1E00000); // mvn r0, r0
757- break;
758- default:
759- error("Unknown unary op %d\n", op);
760- break;
896+ Type* pR0Type = getR0Type();
897+ TypeTag tag = collapseType(pR0Type->tag);
898+ switch(tag) {
899+ case TY_INT:
900+ switch(op) {
901+ case OP_MINUS:
902+ o4(0xE3A01000); // mov r1, #0
903+ o4(0xE0410000); // sub r0,r1,r0
904+ break;
905+ case OP_BIT_NOT:
906+ o4(0xE1E00000); // mvn r0, r0
907+ break;
908+ default:
909+ error("Unknown unary op %d\n", op);
910+ break;
911+ }
912+ break;
913+ case TY_FLOAT:
914+ case TY_DOUBLE:
915+ switch (op) {
916+ case OP_MINUS:
917+ if (tag == TY_FLOAT) {
918+ callRuntime((void*) runtime_op_neg_f);
919+ } else {
920+ callRuntime((void*) runtime_op_neg_d);
921+ }
922+ break;
923+ case OP_BIT_NOT:
924+ error("Can't apply '~' operator to a float or double.");
925+ break;
926+ default:
927+ error("Unknown unary op %d\n", op);
928+ break;
929+ }
930+ break;
931+ default:
932+ error("genUnaryOp unsupported type");
933+ break;
761934 }
762935 }
763936
764937 virtual void pushR0() {
765938 LOG_API("pushR0();\n");
766- o4(0xE92D0001); // stmfd sp!,{r0}
767- mStackUse += 4;
939+ Type* pR0Type = getR0Type();
940+ TypeTag r0ct = collapseType(pR0Type->tag);
941+ if (r0ct != TY_DOUBLE) {
942+ o4(0xE92D0001); // stmfd sp!,{r0}
943+ mStackUse += 4;
944+ } else {
945+ o4(0xE92D0003); // stmfd sp!,{r0,r1}
946+ mStackUse += 8;
947+ }
768948 pushType();
769949 LOG_STACK("pushR0: %d\n", mStackUse);
770950 }
@@ -772,20 +952,24 @@ class Compiler : public ErrorSink {
772952 virtual void storeR0ToTOS(Type* pPointerType) {
773953 LOG_API("storeR0ToTOS(%d);\n", isInt);
774954 assert(pPointerType->tag == TY_POINTER);
775- o4(0xE8BD0002); // ldmfd sp!,{r1}
955+ o4(0xE8BD0004); // ldmfd sp!,{r2}
956+ popType();
776957 mStackUse -= 4;
777958 switch (pPointerType->pHead->tag) {
778959 case TY_INT:
779- o4(0xE5810000); // str r0, [r1]
960+ case TY_FLOAT:
961+ o4(0xE5820000); // str r0, [r2]
780962 break;
781963 case TY_CHAR:
782- o4(0xE5C10000); // strb r0, [r1]
964+ o4(0xE5C20000); // strb r0, [r2]
965+ break;
966+ case TY_DOUBLE:
967+ o4(0xE1C200F0); // strd r0, [r2]
783968 break;
784969 default:
785970 error("storeR0ToTOS: unimplemented type");
786971 break;
787972 }
788- popType();
789973 }
790974
791975 virtual void loadR0FromR0(Type* pPointerType) {
@@ -793,11 +977,15 @@ class Compiler : public ErrorSink {
793977 assert(pPointerType->tag == TY_POINTER);
794978 switch (pPointerType->pHead->tag) {
795979 case TY_INT:
980+ case TY_FLOAT:
796981 o4(0xE5900000); // ldr r0, [r0]
797982 break;
798983 case TY_CHAR:
799984 o4(0xE5D00000); // ldrb r0, [r0]
800985 break;
986+ case TY_DOUBLE:
987+ o4(0xE1C000D0); // ldrd r0, [r0]
988+ break;
801989 default:
802990 error("loadR0FromR0: unimplemented type");
803991 break;
@@ -807,7 +995,7 @@ class Compiler : public ErrorSink {
807995
808996 virtual void leaR0(int ea, Type* pPointerType) {
809997 LOG_API("leaR0(%d);\n", ea);
810- if (ea < LOCAL) {
998+ if (ea > -LOCAL && ea < LOCAL) {
811999 // Local, fp relative
8121000 if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
8131001 error("Offset out of range: %08x", ea);
@@ -829,69 +1017,147 @@ class Compiler : public ErrorSink {
8291017
8301018 virtual void storeR0(int ea, Type* pType) {
8311019 LOG_API("storeR0(%d);\n", ea);
832- if (ea < LOCAL) {
833- // Local, fp relative
834- if (ea < -4095 || ea > 4095) {
835- error("Offset out of range: %08x", ea);
836- }
837- if (ea < 0) {
838- o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
839- } else {
840- o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
841- }
842- } else{
843- // Global, absolute
844- o4(0xE59F1000); // ldr r1, .L1
845- o4(0xEA000000); // b .L99
846- o4(ea); // .L1: .word 0
847- o4(0xE5810000); // .L99: str r0, [r1]
1020+ TypeTag tag = pType->tag;
1021+ switch (tag) {
1022+ case TY_INT:
1023+ case TY_FLOAT:
1024+ if (ea > -LOCAL && ea < LOCAL) {
1025+ // Local, fp relative
1026+ if (ea < -4095 || ea > 4095) {
1027+ error("Offset out of range: %08x", ea);
1028+ }
1029+ if (ea < 0) {
1030+ o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
1031+ } else {
1032+ o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
1033+ }
1034+ } else{
1035+ // Global, absolute
1036+ o4(0xE59F1000); // ldr r1, .L1
1037+ o4(0xEA000000); // b .L99
1038+ o4(ea); // .L1: .word 0
1039+ o4(0xE5810000); // .L99: str r0, [r1]
1040+ }
1041+ break;
1042+ case TY_DOUBLE:
1043+ if ((ea & 0x7) != 0) {
1044+ error("double address is not aligned: %d", ea);
1045+ }
1046+ if (ea > -LOCAL && ea < LOCAL) {
1047+ // Local, fp relative
1048+ if (ea < -4095 || ea > 4095) {
1049+ error("Offset out of range: %08x", ea);
1050+ }
1051+ if (ea < 0) {
1052+ o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
1053+ o4(0xE50B1000 | (0xfff & (-ea + 4))); // str r1, [fp,#-ea+4]
1054+#if 0
1055+ // strd doesn't seem to work. Is encoding wrong?
1056+ } else if (ea < 0) {
1057+ o4(0xE1CB000F | ((0xff & (-ea)) << 4)); // strd r0, [fp,#-ea]
1058+ } else if (ea < 256) {
1059+ o4(0xE14B000F | ((0xff & ea) << 4)); // strd r0, [fp,#ea]
1060+#endif
1061+ } else {
1062+ o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
1063+ o4(0xE58B1000 | (0xfff & (ea + 4))); // str r1, [fp,#ea+4]
1064+ }
1065+ } else{
1066+ // Global, absolute
1067+ o4(0xE59F2000); // ldr r2, .L1
1068+ o4(0xEA000000); // b .L99
1069+ o4(ea); // .L1: .word 0
1070+ o4(0xE1C200F0); // .L99: strd r0, [r2]
1071+ }
1072+ break;
1073+ default:
1074+ error("Unable to store to type %d", tag);
1075+ break;
8481076 }
8491077 }
8501078
8511079 virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
8521080 LOG_API("loadR0(%d, %d, %d, %d);\n", ea, isIncDec, op, pType);
853- if (ea < LOCAL) {
854- // Local, fp relative
855- if (ea < -4095 || ea > 4095) {
856- error("Offset out of range: %08x", ea);
857- }
858- if (ea < 0) {
859- o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
860- } else {
861- o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
862- }
863- } else {
864- // Global, absolute
865- o4(0xE59F2000); // ldr r2, .L1
866- o4(0xEA000000); // b .L99
867- o4(ea); // .L1: .word ea
868- o4(0xE5920000); // .L99: ldr r0, [r2]
869- }
1081+ TypeTag tag = collapseType(pType->tag);
1082+ switch (tag) {
1083+ case TY_INT:
1084+ case TY_FLOAT:
1085+ if (ea < LOCAL) {
1086+ // Local, fp relative
1087+ if (ea < -4095 || ea > 4095) {
1088+ error("Offset out of range: %08x", ea);
1089+ }
1090+ if (ea < 0) {
1091+ o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
1092+ } else {
1093+ o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
1094+ }
1095+ } else {
1096+ // Global, absolute
1097+ o4(0xE59F2000); // ldr r2, .L1
1098+ o4(0xEA000000); // b .L99
1099+ o4(ea); // .L1: .word ea
1100+ o4(0xE5920000); // .L99: ldr r0, [r2]
1101+ }
8701102
871- if (isIncDec) {
872- switch (op) {
873- case OP_INCREMENT:
874- o4(0xE2801001); // add r1, r0, #1
875- break;
876- case OP_DECREMENT:
877- o4(0xE2401001); // sub r1, r0, #1
1103+ if (isIncDec) {
1104+ if (tag == TY_INT) {
1105+ switch (op) {
1106+ case OP_INCREMENT:
1107+ o4(0xE2801001); // add r1, r0, #1
1108+ break;
1109+ case OP_DECREMENT:
1110+ o4(0xE2401001); // sub r1, r0, #1
1111+ break;
1112+ default:
1113+ error("unknown opcode: %d", op);
1114+ }
1115+ if (ea < LOCAL) {
1116+ // Local, fp relative
1117+ // Don't need range check, was already checked above
1118+ if (ea < 0) {
1119+ o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
1120+ } else {
1121+ o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
1122+ }
1123+ } else{
1124+ // Global, absolute
1125+ // r2 is already set up from before.
1126+ o4(0xE5821000); // str r1, [r2]
1127+ }
1128+ }
1129+ else {
1130+ error("inc/dec not implemented for float.");
1131+ }
1132+ }
8781133 break;
879- default:
880- error("unknown opcode: %d", op);
881- }
882- if (ea < LOCAL) {
883- // Local, fp relative
884- // Don't need range check, was already checked above
885- if (ea < 0) {
886- o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
1134+ case TY_DOUBLE:
1135+ if ((ea & 0x7) != 0) {
1136+ error("double address is not aligned: %d", ea);
1137+ }
1138+ if (ea < LOCAL) {
1139+ // Local, fp relative
1140+ if (ea < -4095 || ea > 4095) {
1141+ error("Offset out of range: %08x", ea);
1142+ }
1143+ if (ea < 0) {
1144+ o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
1145+ o4(0xE51B1000 | (0xfff & (-ea+4))); // ldr r1, [fp,#-ea+4]
1146+ } else {
1147+ o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
1148+ o4(0xE59B1000 | (0xfff & (ea+4))); // ldr r0, [fp,#ea+4]
1149+ }
8871150 } else {
888- o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
1151+ // Global, absolute
1152+ o4(0xE59F2000); // ldr r2, .L1
1153+ o4(0xEA000000); // b .L99
1154+ o4(ea); // .L1: .word ea
1155+ o4(0xE1C200D0); // .L99: ldrd r0, [r2]
8891156 }
890- } else{
891- // Global, absolute
892- // r2 is already set up from before.
893- o4(0xE5821000); // str r1, [r2]
894- }
1157+ break;
1158+ default:
1159+ error("Unable to load type %d", tag);
1160+ break;
8951161 }
8961162 setR0Type(pType);
8971163 }
@@ -900,11 +1166,32 @@ class Compiler : public ErrorSink {
9001166 Type* pR0Type = getR0Type();
9011167 if (bitsSame(pType, pR0Type)) {
9021168 // do nothing special
903- } else if (isFloatType(pType) && isFloatType(pR0Type)) {
904- // do nothing special, both held in same register on x87.
9051169 } else {
906- error("Incompatible types old: %d new: %d",
907- pR0Type->tag, pType->tag);
1170+ TypeTag r0Tag = collapseType(pR0Type->tag);
1171+ TypeTag destTag = collapseType(pType->tag);
1172+ if (r0Tag == TY_INT) {
1173+ if (destTag == TY_FLOAT) {
1174+ callRuntime((void*) runtime_int_to_float);
1175+ } else {
1176+ assert(destTag == TY_DOUBLE);
1177+ callRuntime((void*) runtime_int_to_double);
1178+ }
1179+ } else if (r0Tag == TY_FLOAT) {
1180+ if (destTag == TY_INT) {
1181+ callRuntime((void*) runtime_float_to_int);
1182+ } else {
1183+ assert(destTag == TY_DOUBLE);
1184+ callRuntime((void*) runtime_float_to_double);
1185+ }
1186+ } else {
1187+ assert (r0Tag == TY_DOUBLE);
1188+ if (destTag == TY_INT) {
1189+ callRuntime((void*) runtime_double_to_int);
1190+ } else {
1191+ assert(destTag == TY_FLOAT);
1192+ callRuntime((void*) runtime_double_to_float);
1193+ }
1194+ }
9081195 }
9091196 setR0Type(pType);
9101197 }
@@ -916,19 +1203,42 @@ class Compiler : public ErrorSink {
9161203
9171204 virtual size_t storeR0ToArg(int l) {
9181205 LOG_API("storeR0ToArg(%d);\n", l);
919- if (l < 0 || l > 4096-4) {
920- error("l out of range for stack offset: 0x%08x", l);
1206+ Type* pR0Type = getR0Type();
1207+ TypeTag r0ct = collapseType(pR0Type->tag);
1208+ switch(r0ct) {
1209+ case TY_INT:
1210+ case TY_FLOAT:
1211+ if (l < 0 || l > 4096-4) {
1212+ error("l out of range for stack offset: 0x%08x", l);
1213+ }
1214+ o4(0xE58D0000 + l); // str r0, [sp, #l]
1215+ return 4;
1216+ case TY_DOUBLE: {
1217+ // Align to 8 byte boundary
1218+ int l2 = (l + 7) & ~7;
1219+ if (l2 < 0 || l2 > 4096-8) {
1220+ error("l out of range for stack offset: 0x%08x", l);
1221+ }
1222+ o4(0xE58D0000 + l2); // str r0, [sp, #l]
1223+ o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4]
1224+ return (l2 - l) + 8;
1225+ }
1226+ default:
1227+ assert(false);
1228+ return 0;
9211229 }
922- o4(0xE58D0000 + l); // str r0, [sp, #4]
923- return 4;
9241230 }
9251231
926- virtual void endFunctionCallArguments(int a, int l) {
1232+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
9271233 LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l);
928- int argCount = l >> 2;
9291234 int argumentStackUse = l;
930- if (argCount > 0) {
931- int regArgCount = argCount > 4 ? 4 : argCount;
1235+ // Have to calculate register arg count from actual stack size,
1236+ // in order to properly handle ... functions.
1237+ int regArgCount = l >> 2;
1238+ if (regArgCount > 4) {
1239+ regArgCount = 4;
1240+ }
1241+ if (regArgCount > 0) {
9321242 argumentStackUse -= regArgCount * 4;
9331243 o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
9341244 }
@@ -989,10 +1299,16 @@ class Compiler : public ErrorSink {
9891299 o4(0xE12FFF3C); // blx r12
9901300 }
9911301
992- virtual void adjustStackAfterCall(int l, bool isIndirect) {
1302+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
9931303 LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect);
9941304 int argCount = l >> 2;
995- int stackArgs = argCount > 4 ? argCount - 4 : 0;
1305+ // Have to calculate register arg count from actual stack size,
1306+ // in order to properly handle ... functions.
1307+ int regArgCount = l >> 2;
1308+ if (regArgCount > 4) {
1309+ regArgCount = 4;
1310+ }
1311+ int stackArgs = argCount - regArgCount;
9961312 int stackUse = stackArgs + (isIndirect ? 1 : 0)
9971313 + (mStackAlignmentAdjustment >> 2);
9981314 if (stackUse) {
@@ -1062,7 +1378,7 @@ class Compiler : public ErrorSink {
10621378 /**
10631379 * alignment (in bytes) for this type of data
10641380 */
1065- virtual size_t alignment(Type* pType){
1381+ virtual size_t alignmentOf(Type* pType){
10661382 switch(pType->tag) {
10671383 case TY_DOUBLE:
10681384 return 8;
@@ -1141,20 +1457,251 @@ class Compiler : public ErrorSink {
11411457 return BRANCH_REL_ADDRESS_MASK & (value >> 2);
11421458 }
11431459
1144- typedef int (*int2FnPtr)(int a, int b);
1145- void callRuntime(int2FnPtr fn) {
1146- o4(0xE59F2000); // ldr r2, .L1
1460+ int calcRegArgCount(Type* pDecl) {
1461+ int reg = 0;
1462+ Type* pArgs = pDecl->pTail;
1463+ while (pArgs && reg < 4) {
1464+ Type* pArg = pArgs->pHead;
1465+ if ( pArg->tag == TY_DOUBLE) {
1466+ int evenReg = (reg + 1) & ~1;
1467+ if (evenReg >= 4) {
1468+ break;
1469+ }
1470+ reg = evenReg + 2;
1471+ } else {
1472+ reg++;
1473+ }
1474+ pArgs = pArgs->pTail;
1475+ }
1476+ return reg;
1477+ }
1478+
1479+ /* Pop TOS to R1
1480+ * Make sure both R0 and TOS are floats. (Could be ints)
1481+ * We know that at least one of R0 and TOS is already a float
1482+ */
1483+ void setupFloatArgs() {
1484+ Type* pR0Type = getR0Type();
1485+ Type* pTOSType = getTOSType();
1486+ TypeTag tagR0 = collapseType(pR0Type->tag);
1487+ TypeTag tagTOS = collapseType(pTOSType->tag);
1488+ if (tagR0 != TY_FLOAT) {
1489+ assert(tagR0 == TY_INT);
1490+ callRuntime((void*) runtime_int_to_float);
1491+ }
1492+ if (tagTOS != TY_FLOAT) {
1493+ assert(tagTOS == TY_INT);
1494+ assert(tagR0 == TY_FLOAT);
1495+ o4(0xE92D0001); // stmfd sp!,{r0} // push R0
1496+ o4(0xE59D0004); // ldr r0, [sp, #4]
1497+ callRuntime((void*) runtime_int_to_float);
1498+ o4(0xE1A01000); // mov r1, r0
1499+ o4(0xE8BD0001); // ldmfd sp!,{r0} // pop R0
1500+ o4(0xE28DD004); // add sp, sp, #4 // Pop sp
1501+ } else {
1502+ // Pop TOS
1503+ o4(0xE8BD0002); // ldmfd sp!,{r1}
1504+ }
1505+ mStackUse -= 4;
1506+ popType();
1507+ }
1508+
1509+ /* Pop TOS into R2..R3
1510+ * Make sure both R0 and TOS are doubles. Could be floats or ints.
1511+ * We know that at least one of R0 and TOS are already a double.
1512+ */
1513+
1514+ void setupDoubleArgs() {
1515+ Type* pR0Type = getR0Type();
1516+ Type* pTOSType = getTOSType();
1517+ TypeTag tagR0 = collapseType(pR0Type->tag);
1518+ TypeTag tagTOS = collapseType(pTOSType->tag);
1519+ if (tagR0 != TY_DOUBLE) {
1520+ if (tagR0 == TY_INT) {
1521+ callRuntime((void*) runtime_int_to_double);
1522+ } else {
1523+ assert(tagR0 == TY_FLOAT);
1524+ callRuntime((void*) runtime_float_to_double);
1525+ }
1526+ }
1527+ if (tagTOS != TY_DOUBLE) {
1528+ o4(0xE92D0003); // stmfd sp!,{r0,r1} // push r0,r1
1529+ o4(0xE59D0008); // ldr r0, [sp, #8]
1530+ if (tagTOS == TY_INT) {
1531+ callRuntime((void*) runtime_int_to_double);
1532+ } else {
1533+ assert(tagTOS == TY_FLOAT);
1534+ callRuntime((void*) runtime_float_to_double);
1535+ }
1536+ o4(0xE1A02000); // mov r2, r0
1537+ o4(0xE1A03001); // mov r3, r1
1538+ o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0
1539+ o4(0xE28DD004); // add sp, sp, #4 // Pop sp
1540+ mStackUse -= 4;
1541+ } else {
1542+ o4(0xE8BD000C); // ldmfd sp!,{r2,r3}
1543+ mStackUse -= 8;
1544+ }
1545+ popType();
1546+ }
1547+
1548+ void callRuntime(void* fn) {
1549+ o4(0xE59FC000); // ldr r12, .L1
11471550 o4(0xEA000000); // b .L99
11481551 o4((int) fn); //.L1: .word fn
1149- o4(0xE12FFF32); //.L99: blx r2
1552+ o4(0xE12FFF3C); //.L99: blx r12
1553+ }
1554+
1555+ // Integer math:
1556+
1557+ static int runtime_DIV(int b, int a) {
1558+ return a / b;
1559+ }
1560+
1561+ static int runtime_MOD(int b, int a) {
1562+ return a % b;
1563+ }
1564+
1565+ // Comparison to zero
1566+
1567+ static int runtime_is_non_zero_f(float a) {
1568+ return a != 0;
1569+ }
1570+
1571+ static int runtime_is_non_zero_d(double a) {
1572+ return a != 0;
1573+ }
1574+
1575+ // Comparison to zero
1576+
1577+ static int runtime_is_zero_f(float a) {
1578+ return a == 0;
1579+ }
1580+
1581+ static int runtime_is_zero_d(double a) {
1582+ return a == 0;
1583+ }
1584+
1585+ // Type conversion
1586+
1587+ static int runtime_float_to_int(float a) {
1588+ return (int) a;
1589+ }
1590+
1591+ static double runtime_float_to_double(float a) {
1592+ return (double) a;
11501593 }
11511594
1152- static int runtime_DIV(int a, int b) {
1153- return b / a;
1595+ static int runtime_double_to_int(double a) {
1596+ return (int) a;
11541597 }
11551598
1156- static int runtime_MOD(int a, int b) {
1157- return b % a;
1599+ static float runtime_double_to_float(double a) {
1600+ return (float) a;
1601+ }
1602+
1603+ static float runtime_int_to_float(int a) {
1604+ return (float) a;
1605+ }
1606+
1607+ static double runtime_int_to_double(int a) {
1608+ return (double) a;
1609+ }
1610+
1611+ // Comparisons float
1612+
1613+ static int runtime_cmp_eq_ff(float b, float a) {
1614+ return a == b;
1615+ }
1616+
1617+ static int runtime_cmp_ne_ff(float b, float a) {
1618+ return a != b;
1619+ }
1620+
1621+ static int runtime_cmp_lt_ff(float b, float a) {
1622+ return a < b;
1623+ }
1624+
1625+ static int runtime_cmp_le_ff(float b, float a) {
1626+ return a <= b;
1627+ }
1628+
1629+ static int runtime_cmp_ge_ff(float b, float a) {
1630+ return a >= b;
1631+ }
1632+
1633+ static int runtime_cmp_gt_ff(float b, float a) {
1634+ return a > b;
1635+ }
1636+
1637+ // Comparisons double
1638+
1639+ static int runtime_cmp_eq_dd(double b, double a) {
1640+ return a == b;
1641+ }
1642+
1643+ static int runtime_cmp_ne_dd(double b, double a) {
1644+ return a != b;
1645+ }
1646+
1647+ static int runtime_cmp_lt_dd(double b, double a) {
1648+ return a < b;
1649+ }
1650+
1651+ static int runtime_cmp_le_dd(double b, double a) {
1652+ return a <= b;
1653+ }
1654+
1655+ static int runtime_cmp_ge_dd(double b, double a) {
1656+ return a >= b;
1657+ }
1658+
1659+ static int runtime_cmp_gt_dd(double b, double a) {
1660+ return a > b;
1661+ }
1662+
1663+ // Math float
1664+
1665+ static float runtime_op_add_ff(float b, float a) {
1666+ return a + b;
1667+ }
1668+
1669+ static float runtime_op_sub_ff(float b, float a) {
1670+ return a - b;
1671+ }
1672+
1673+ static float runtime_op_mul_ff(float b, float a) {
1674+ return a * b;
1675+ }
1676+
1677+ static float runtime_op_div_ff(float b, float a) {
1678+ return a / b;
1679+ }
1680+
1681+ static float runtime_op_neg_f(float a) {
1682+ return -a;
1683+ }
1684+
1685+ // Math double
1686+
1687+ static double runtime_op_add_dd(double b, double a) {
1688+ return a + b;
1689+ }
1690+
1691+ static double runtime_op_sub_dd(double b, double a) {
1692+ return a - b;
1693+ }
1694+
1695+ static double runtime_op_mul_dd(double b, double a) {
1696+ return a * b;
1697+ }
1698+
1699+ static double runtime_op_div_dd(double b, double a) {
1700+ return a / b;
1701+ }
1702+
1703+ static double runtime_op_neg_d(double a) {
1704+ return -a;
11581705 }
11591706
11601707 static const int STACK_ALIGNMENT = 8;
@@ -1176,12 +1723,12 @@ class Compiler : public ErrorSink {
11761723
11771724 /* returns address to patch with local variable size
11781725 */
1179- virtual int functionEntry(int argCount) {
1726+ virtual int functionEntry(Type* pDecl) {
11801727 o(0xe58955); /* push %ebp, mov %esp, %ebp */
11811728 return oad(0xec81, 0); /* sub $xxx, %esp */
11821729 }
11831730
1184- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
1731+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
11851732 o(0xc3c9); /* leave, ret */
11861733 *(int *) localVariableAddress = localVariableSize; /* save local variables */
11871734 }
@@ -1333,7 +1880,6 @@ class Compiler : public ErrorSink {
13331880 error("Unsupported binary floating operation.");
13341881 break;
13351882 }
1336- popType();
13371883 setR0Type(pResultType);
13381884 }
13391885 }
@@ -1368,7 +1914,7 @@ class Compiler : public ErrorSink {
13681914 o(0x01f083); // xorl $1, %eax
13691915 break;
13701916 default:
1371- error("genUnaryCmp unsupported type");
1917+ error("gUnaryCmp unsupported type");
13721918 break;
13731919 }
13741920 }
@@ -1607,7 +2153,7 @@ class Compiler : public ErrorSink {
16072153 }
16082154 }
16092155
1610- virtual void endFunctionCallArguments(int a, int l) {
2156+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
16112157 * (int*) a = l;
16122158 }
16132159
@@ -1626,7 +2172,7 @@ class Compiler : public ErrorSink {
16262172 oad(0x2494ff, l); /* call *xxx(%esp) */
16272173 }
16282174
1629- virtual void adjustStackAfterCall(int l, bool isIndirect) {
2175+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
16302176 if (isIndirect) {
16312177 l += 4;
16322178 }
@@ -1668,13 +2214,8 @@ class Compiler : public ErrorSink {
16682214 /**
16692215 * Alignment (in bytes) for this type of data
16702216 */
1671- virtual size_t alignment(Type* pType){
1672- switch(pType->tag) {
1673- case TY_DOUBLE:
1674- return 8;
1675- default:
1676- return 4;
1677- }
2217+ virtual size_t alignmentOf(Type* pType){
2218+ return 4;
16782219 }
16792220
16802221 /**
@@ -1782,6 +2323,7 @@ class Compiler : public ErrorSink {
17822323 o(0x58); // pop %eax
17832324 }
17842325 }
2326+ popType();
17852327 }
17862328 };
17872329
@@ -1811,16 +2353,16 @@ class Compiler : public ErrorSink {
18112353
18122354 /* returns address to patch with local variable size
18132355 */
1814- virtual int functionEntry(int argCount) {
1815- int result = mpBase->functionEntry(argCount);
1816- fprintf(stderr, "functionEntry(%d) -> %d\n", argCount, result);
2356+ virtual int functionEntry(Type* pDecl) {
2357+ int result = mpBase->functionEntry(pDecl);
2358+ fprintf(stderr, "functionEntry(pDecl) -> %d\n", result);
18172359 return result;
18182360 }
18192361
1820- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
1821- fprintf(stderr, "functionExit(%d, %d, %d)\n",
1822- argCount, localVariableAddress, localVariableSize);
1823- mpBase->functionExit(argCount, localVariableAddress, localVariableSize);
2362+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
2363+ fprintf(stderr, "functionExit(pDecl, %d, %d)\n",
2364+ localVariableAddress, localVariableSize);
2365+ mpBase->functionExit(pDecl, localVariableAddress, localVariableSize);
18242366 }
18252367
18262368 /* load immediate value */
@@ -1914,9 +2456,9 @@ class Compiler : public ErrorSink {
19142456 return mpBase->storeR0ToArg(l);
19152457 }
19162458
1917- virtual void endFunctionCallArguments(int a, int l) {
2459+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
19182460 fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l);
1919- mpBase->endFunctionCallArguments(a, l);
2461+ mpBase->endFunctionCallArguments(pDecl, a, l);
19202462 }
19212463
19222464 virtual int callForward(int symbol, Type* pFunc) {
@@ -1935,9 +2477,9 @@ class Compiler : public ErrorSink {
19352477 mpBase->callIndirect(l, pFunc);
19362478 }
19372479
1938- virtual void adjustStackAfterCall(int l, bool isIndirect) {
1939- fprintf(stderr, "adjustStackAfterCall(%d, %d)\n", l, isIndirect);
1940- mpBase->adjustStackAfterCall(l, isIndirect);
2480+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
2481+ fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect);
2482+ mpBase->adjustStackAfterCall(pDecl, l, isIndirect);
19412483 }
19422484
19432485 virtual int jumpOffset() {
@@ -1963,8 +2505,8 @@ class Compiler : public ErrorSink {
19632505 /**
19642506 * Alignment (in bytes) for this type of data
19652507 */
1966- virtual size_t alignment(Type* pType){
1967- return mpBase->alignment(pType);
2508+ virtual size_t alignmentOf(Type* pType){
2509+ return mpBase->alignmentOf(pType);
19682510 }
19692511
19702512 /**
@@ -3206,15 +3748,16 @@ class Compiler : public ErrorSink {
32063748
32073749 /* function call */
32083750 if (accept('(')) {
3209- Type* pArgList = NULL;
3751+ Type* pDecl = NULL;
32103752 VariableInfo* pVI = NULL;
32113753 if (n == 1) { // Indirect function call, push address of fn.
3212- pArgList = pGen->getR0Type()->pTail;
3754+ pDecl = pGen->getR0Type();
32133755 pGen->pushR0();
32143756 } else {
32153757 pVI = VI(t);
3216- pArgList = pVI->pType->pTail;
3758+ pDecl = pVI->pType;
32173759 }
3760+ Type* pArgList = pDecl->pTail;
32183761 bool varArgs = pArgList == NULL;
32193762 /* push args and invert order */
32203763 a = pGen->beginFunctionCallArguments();
@@ -3252,7 +3795,7 @@ class Compiler : public ErrorSink {
32523795 if (! varArgs && pArgList) {
32533796 error ("Expected more argument(s). Saw %d", argCount);
32543797 }
3255- pGen->endFunctionCallArguments(a, l);
3798+ pGen->endFunctionCallArguments(pDecl, a, l);
32563799 skip(')');
32573800 if (!n) {
32583801 /* forward reference */
@@ -3264,7 +3807,7 @@ class Compiler : public ErrorSink {
32643807 pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset(),
32653808 VI(t)->pType);
32663809 }
3267- pGen->adjustStackAfterCall(l, n == 1);
3810+ pGen->adjustStackAfterCall(pDecl, l, n == 1);
32683811 }
32693812 }
32703813
@@ -3729,8 +4272,9 @@ class Compiler : public ErrorSink {
37294272 }
37304273 int variableAddress = 0;
37314274 addLocalSymbol(pDecl);
4275+ size_t alignment = pGen->alignmentOf(pDecl);
4276+ loc = (loc + alignment - 1) & ~ (alignment-1);
37324277 loc = loc + pGen->sizeOf(pDecl);
3733- loc = loc + 4;
37344278 variableAddress = -loc;
37354279 VI(pDecl->id)->pAddress = (void*) variableAddress;
37364280 if (accept('=')) {
@@ -3809,7 +4353,7 @@ class Compiler : public ErrorSink {
38094353 for(;;) {
38104354 if (name && !name->pAddress) {
38114355 name->pAddress = (int*) allocGlobalSpace(
3812- pGen->alignment(name->pType),
4356+ pGen->alignmentOf(name->pType),
38134357 pGen->sizeOf(name->pType));
38144358 }
38154359 if (accept('=')) {
@@ -3855,16 +4399,18 @@ class Compiler : public ErrorSink {
38554399 Type* pArg = pP->pHead;
38564400 addLocalSymbol(pArg);
38574401 /* read param name and compute offset */
4402+ size_t alignment = pGen->alignmentOf(pArg);
4403+ a = (a + alignment - 1) & ~ (alignment-1);
38584404 VI(pArg->id)->pAddress = (void*) a;
38594405 a = a + pGen->stackSizeOf(pArg);
38604406 argCount++;
38614407 }
38624408 rsym = loc = 0;
38634409 pReturnType = pDecl->pHead;
3864- a = pGen->functionEntry(argCount);
4410+ a = pGen->functionEntry(pDecl);
38654411 block(0, true);
38664412 pGen->gsym(rsym);
3867- pGen->functionExit(argCount, a, loc);
4413+ pGen->functionExit(pDecl, a, loc);
38684414 mLocals.popLevel();
38694415 }
38704416 }
--- a/libacc/tests/data/float.c
+++ b/libacc/tests/data/float.c
@@ -38,13 +38,12 @@ void testVars(float arg0, float arg1, double arg2, double arg3) {
3838 * (float*) & f0 = 1.1f;
3939 * (double*) & d0 = 3.3;
4040 printf("cast lval: %g %g %g %g\n", f0, f1, d0, d1);
41-
4241 }
4342
4443 int main() {
4544 printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);
4645 printf(" ftoi(1.4f)=%d\n", ftoi(1.4f));
47- printf(" dtoi(2.4f)=%d\n", dtoi(2.4f));
46+ printf(" dtoi(2.4)=%d\n", dtoi(2.4));
4847 printf(" itof(3)=%g\n", itof(3));
4948 printf(" itod(4)=%g\n", itod(4));
5049 testVars(1.0f, 2.0f, 3.0, 4.0);
--- a/libacc/tests/data/flops.c
+++ b/libacc/tests/data/flops.c
@@ -4,7 +4,7 @@ void unaryOps() {
44 // Unary ops
55 printf("-%g = %g\n", 1.1, -1.1);
66 printf("!%g = %d\n", 1.2, !1.2);
7- printf("!%g = %d\n", 0.0, !0,0);
7+ printf("!%g = %d\n", 0.0, !0.0);
88 }
99
1010 void binaryOps() {
@@ -75,6 +75,7 @@ void comparisonOpsff() {
7575 comparisonTestff(1.0f, 1.0f);
7676 comparisonTestff(2.0f, 1.0f);
7777 }
78+
7879 void comparisonTestid(int a, double b) {
7980 printf("%d op %g: < %d <= %d == %d >= %d > %d != %d\n",
8081 a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
@@ -82,9 +83,9 @@ void comparisonTestid(int a, double b) {
8283
8384 void comparisonOpsid() {
8485 printf("int op double:\n");
85- comparisonTestid(1, 2.0f);
86- comparisonTestid(1, 1.0f);
87- comparisonTestid(2, 1.0f);
86+ comparisonTestid(1, 2.0);
87+ comparisonTestid(1, 1.0);
88+ comparisonTestid(2, 1.0);
8889 }
8990 void comparisonTestdi(double a, int b) {
9091 printf("%g op %d: < %d <= %d == %d >= %d > %d != %d\n",
@@ -117,10 +118,34 @@ void testBranching() {
117118 printf("branching: %d %d %d\n", branch(-1.0), branch(0.0), branch(1.0));
118119 }
119120
121+void testpassi(int a, int b, int c, int d, int e, int f, int g, int h) {
122+ printf("testpassi: %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h);
123+}
124+
125+void testpassf(float a, float b, float c, float d, float e, float f, float g, float h) {
126+ printf("testpassf: %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h);
127+}
128+
129+void testpassd(double a, double b, double c, double d, double e, double f, double g, double h) {
130+ printf("testpassd: %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h);
131+}
132+
133+void testpassidf(int i, double d, float f) {
134+ printf("testpassidf: %d %g %g\n", i, d, f);
135+}
136+
137+void testParameterPassing() {
138+ testpassi(1, 2, 3, 4, 5, 6, 7, 8);
139+ testpassf(1, 2, 3, 4, 5, 6, 7, 8);
140+ testpassd(1, 2, 3, 4, 5, 6, 7, 8);
141+ testpassidf(1, 2.0, 3.0f);
142+}
143+
120144 int main() {
121145 unaryOps();
122146 binaryOps();
123147 comparisonOps();
124148 testBranching();
149+ testParameterPassing();
125150 return 0;
126151 }
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -118,7 +118,7 @@ class TestACC(unittest.TestCase):
118118 def testRunFloat(self):
119119 self.compileCheck(["-R", "data/float.c"],
120120 "Executing compiled code:\nresult: 0\n",
121- "int: 1 float: 2.2 double: 3.3\n ftoi(1.4f)=1\n dtoi(2.4f)=2\n itof(3)=3\n itod(4)=4\nglobals: 1 2 3 4\nargs: 1 2 3 4\nlocals: 1 2 3 4\ncast rval: 2 4\ncast lval: 1.1 2 3.3 4\n")
121+ "int: 1 float: 2.2 double: 3.3\n ftoi(1.4f)=1\n dtoi(2.4)=2\n itof(3)=3\n itod(4)=4\nglobals: 1 2 3 4\nargs: 1 2 3 4\nlocals: 1 2 3 4\ncast rval: 2 4\ncast lval: 1.1 2 3.3 4\n")
122122
123123 def testRunFlops(self):
124124 self.compileCheck(["-R", "data/flops.c"],
@@ -171,7 +171,12 @@ class TestACC(unittest.TestCase):
171171 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
172172 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
173173 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
174- "branching: 1 0 1\n")
174+ "branching: 1 0 1\n" +
175+ "testpassi: 1 2 3 4 5 6 7 8\n" +
176+ "testpassf: 1 2 3 4 5 6 7 8\n" +
177+ "testpassd: 1 2 3 4 5 6 7 8\n" +
178+ "testpassidf: 1 2 3\n"
179+ )
175180
176181 def testArmRunReturnVal(self):
177182 self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"],