Merge change 6822
* changes:
nexus: Rollup update for nexus
diff --git a/adb/adb.h b/adb/adb.h
index b9ed556..95610a7 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -33,7 +33,7 @@
#define ADB_VERSION_MAJOR 1 // Used for help/version information
#define ADB_VERSION_MINOR 0 // Used for help/version information
-#define ADB_SERVER_VERSION 20 // Increment this when we want to force users to start a new adb server
+#define ADB_SERVER_VERSION 21 // Increment this when we want to force users to start a new adb server
typedef struct amessage amessage;
typedef struct apacket apacket;
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index c2dea56..219a436 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -270,7 +270,7 @@
}
/* Emit a function prolog.
- * argCount is the number of arguments.
+ * pDecl is the function declaration, which gives the arguments.
* Save the old value of the FP.
* Set the new value of the FP.
* Convert from the native platform calling convention to
@@ -282,7 +282,7 @@
* functionExit().
* returns address to patch with local variable size.
*/
- virtual int functionEntry(int argCount) = 0;
+ virtual int functionEntry(Type* pDecl) = 0;
/* Emit a function epilog.
* Restore the old SP and FP register values.
@@ -291,7 +291,7 @@
* localVariableAddress - returned from functionEntry()
* localVariableSize - the size in bytes of the local variables.
*/
- virtual void functionExit(int argCount, int localVariableAddress,
+ virtual void functionExit(Type* pDecl, int localVariableAddress,
int localVariableSize) = 0;
/* load immediate value to R0 */
@@ -398,7 +398,7 @@
* On ARM for example you would pop the first 5 arguments into
* R0..R4
*/
- virtual void endFunctionCallArguments(int a, int l) = 0;
+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) = 0;
/* Emit a call to an unknown function. The argument "symbol" needs to
* be stored in the location where the address should go. It forms
@@ -424,7 +424,7 @@
* is true if this was an indirect call. (In which case the
* address of the function is stored at location SP + l.)
*/
- virtual void adjustStackAfterCall(int l, bool isIndirect) = 0;
+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0;
/* Print a disassembly of the assembled code to out. Return
* non-zero if there is an error.
@@ -452,7 +452,7 @@
/**
* Memory alignment (in bytes) for this type of data
*/
- virtual size_t alignment(Type* type) = 0;
+ virtual size_t alignmentOf(Type* type) = 0;
/**
* Array element alignment (in bytes) for this type of data.
@@ -561,15 +561,15 @@
/* returns address to patch with local variable size
*/
- virtual int functionEntry(int argCount) {
- LOG_API("functionEntry(%d);\n", argCount);
+ virtual int functionEntry(Type* pDecl) {
+ LOG_API("functionEntry(%d);\n", pDecl);
mStackUse = 0;
// sp -> arg4 arg5 ...
// Push our register-based arguments back on the stack
- if (argCount > 0) {
- int regArgCount = argCount <= 4 ? argCount : 4;
- o4(0xE92D0000 | ((1 << argCount) - 1)); // stmfd sp!, {}
+ int regArgCount = calcRegArgCount(pDecl);
+ if (regArgCount > 0) {
mStackUse += regArgCount * 4;
+ o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd sp!, {}
}
// sp -> arg0 arg1 ...
o4(0xE92D4800); // stmfd sp!, {fp, lr}
@@ -583,7 +583,7 @@
// STACK_ALIGNMENT, so it won't affect the stack alignment.
}
- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize);
// Round local variable size up to a multiple of stack alignment
localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) /
@@ -601,12 +601,13 @@
// sp -> retadr, arg0, ...
o4(0xE8BD4000); // ldmfd sp!, {lr}
// sp -> arg0 ....
- if (argCount > 0) {
- // We store the PC into the lr so we can adjust the sp before
- // returning. We need to pull off the registers we pushed
- // earlier. We don't need to actually store them anywhere,
- // just adjust the stack.
- int regArgCount = argCount <= 4 ? argCount : 4;
+
+ // We store the PC into the lr so we can adjust the sp before
+ // returning. We need to pull off the registers we pushed
+ // earlier. We don't need to actually store them anywhere,
+ // just adjust the stack.
+ int regArgCount = calcRegArgCount(pDecl);
+ if (regArgCount) {
o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2
}
o4(0xE12FFF1E); // bx lr
@@ -630,8 +631,24 @@
}
virtual void loadFloat(int address, Type* pType) {
- error("Unimplemented.\n");
setR0Type(pType);
+ // Global, absolute address
+ o4(0xE59F0000); // ldr r0, .L1
+ o4(0xEA000000); // b .L99
+ o4(address); // .L1: .word ea
+ // .L99:
+
+ switch (pType->tag) {
+ case TY_FLOAT:
+ o4(0xE5900000); // ldr r0, [r0]
+ break;
+ case TY_DOUBLE:
+ o4(0xE1C000D0); // ldrd r0, [r0]
+ break;
+ default:
+ assert(false);
+ break;
+ }
}
virtual int gjmp(int t) {
@@ -642,6 +659,18 @@
/* l = 0: je, l == 1: jne */
virtual int gtst(bool l, int t) {
LOG_API("gtst(%d, %d);\n", l, t);
+ Type* pR0Type = getR0Type();
+ TypeTag tagR0 = pR0Type->tag;
+ switch(tagR0) {
+ case TY_FLOAT:
+ callRuntime((void*) runtime_is_non_zero_f);
+ break;
+ case TY_DOUBLE:
+ callRuntime((void*) runtime_is_non_zero_d);
+ break;
+ default:
+ break;
+ }
o4(0xE3500000); // cmp r0,#0
int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
return o4(branch | encodeAddress(t));
@@ -649,122 +678,273 @@
virtual void gcmp(int op, Type* pResultType) {
LOG_API("gcmp(%d);\n", op);
- o4(0xE8BD0002); // ldmfd sp!,{r1}
- mStackUse -= 4;
- o4(0xE1510000); // cmp r1, r1
- switch(op) {
- case OP_EQUALS:
- o4(0x03A00001); // moveq r0,#1
- o4(0x13A00000); // movne r0,#0
- break;
- case OP_NOT_EQUALS:
- o4(0x03A00000); // moveq r0,#0
- o4(0x13A00001); // movne r0,#1
- break;
- case OP_LESS_EQUAL:
- o4(0xD3A00001); // movle r0,#1
- o4(0xC3A00000); // movgt r0,#0
- break;
- case OP_GREATER:
- o4(0xD3A00000); // movle r0,#0
- o4(0xC3A00001); // movgt r0,#1
- break;
- case OP_GREATER_EQUAL:
- o4(0xA3A00001); // movge r0,#1
- o4(0xB3A00000); // movlt r0,#0
- break;
- case OP_LESS:
- o4(0xA3A00000); // movge r0,#0
- o4(0xB3A00001); // movlt r0,#1
- break;
- default:
- error("Unknown comparison op %d", op);
- break;
+ Type* pR0Type = getR0Type();
+ Type* pTOSType = getTOSType();
+ TypeTag tagR0 = collapseType(pR0Type->tag);
+ TypeTag tagTOS = collapseType(pTOSType->tag);
+ if (tagR0 == TY_INT && tagTOS == TY_INT) {
+ o4(0xE8BD0002); // ldmfd sp!,{r1}
+ mStackUse -= 4;
+ o4(0xE1510000); // cmp r1, r1
+ switch(op) {
+ case OP_EQUALS:
+ o4(0x03A00001); // moveq r0,#1
+ o4(0x13A00000); // movne r0,#0
+ break;
+ case OP_NOT_EQUALS:
+ o4(0x03A00000); // moveq r0,#0
+ o4(0x13A00001); // movne r0,#1
+ break;
+ case OP_LESS_EQUAL:
+ o4(0xD3A00001); // movle r0,#1
+ o4(0xC3A00000); // movgt r0,#0
+ break;
+ case OP_GREATER:
+ o4(0xD3A00000); // movle r0,#0
+ o4(0xC3A00001); // movgt r0,#1
+ break;
+ case OP_GREATER_EQUAL:
+ o4(0xA3A00001); // movge r0,#1
+ o4(0xB3A00000); // movlt r0,#0
+ break;
+ case OP_LESS:
+ o4(0xA3A00000); // movge r0,#0
+ o4(0xB3A00001); // movlt r0,#1
+ break;
+ default:
+ error("Unknown comparison op %d", op);
+ break;
+ }
+ popType();
+ } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) {
+ setupDoubleArgs();
+ switch(op) {
+ case OP_EQUALS:
+ callRuntime((void*) runtime_cmp_eq_dd);
+ break;
+ case OP_NOT_EQUALS:
+ callRuntime((void*) runtime_cmp_ne_dd);
+ break;
+ case OP_LESS_EQUAL:
+ callRuntime((void*) runtime_cmp_le_dd);
+ break;
+ case OP_GREATER:
+ callRuntime((void*) runtime_cmp_gt_dd);
+ break;
+ case OP_GREATER_EQUAL:
+ callRuntime((void*) runtime_cmp_ge_dd);
+ break;
+ case OP_LESS:
+ callRuntime((void*) runtime_cmp_lt_dd);
+ break;
+ default:
+ error("Unknown comparison op %d", op);
+ break;
+ }
+ } else {
+ setupFloatArgs();
+ switch(op) {
+ case OP_EQUALS:
+ callRuntime((void*) runtime_cmp_eq_ff);
+ break;
+ case OP_NOT_EQUALS:
+ callRuntime((void*) runtime_cmp_ne_ff);
+ break;
+ case OP_LESS_EQUAL:
+ callRuntime((void*) runtime_cmp_le_ff);
+ break;
+ case OP_GREATER:
+ callRuntime((void*) runtime_cmp_gt_ff);
+ break;
+ case OP_GREATER_EQUAL:
+ callRuntime((void*) runtime_cmp_ge_ff);
+ break;
+ case OP_LESS:
+ callRuntime((void*) runtime_cmp_lt_ff);
+ break;
+ default:
+ error("Unknown comparison op %d", op);
+ break;
+ }
}
- popType();
+ setR0Type(pResultType);
}
virtual void genOp(int op) {
LOG_API("genOp(%d);\n", op);
- o4(0xE8BD0002); // ldmfd sp!,{r1}
- mStackUse -= 4;
- switch(op) {
- case OP_MUL:
- o4(0x0E0000091); // mul r0,r1,r0
- break;
- case OP_DIV:
- callRuntime(runtime_DIV);
- break;
- case OP_MOD:
- callRuntime(runtime_MOD);
- break;
- case OP_PLUS:
- o4(0xE0810000); // add r0,r1,r0
- break;
- case OP_MINUS:
- o4(0xE0410000); // sub r0,r1,r0
- break;
- case OP_SHIFT_LEFT:
- o4(0xE1A00011); // lsl r0,r1,r0
- break;
- case OP_SHIFT_RIGHT:
- o4(0xE1A00051); // asr r0,r1,r0
- break;
- case OP_BIT_AND:
- o4(0xE0010000); // and r0,r1,r0
- break;
- case OP_BIT_XOR:
- o4(0xE0210000); // eor r0,r1,r0
- break;
- case OP_BIT_OR:
- o4(0xE1810000); // orr r0,r1,r0
- break;
- case OP_BIT_NOT:
- o4(0xE1E00000); // mvn r0, r0
- break;
- default:
- error("Unimplemented op %d\n", op);
- break;
+ Type* pR0Type = getR0Type();
+ Type* pTOSType = getTOSType();
+ TypeTag tagR0 = collapseType(pR0Type->tag);
+ TypeTag tagTOS = collapseType(pTOSType->tag);
+ if (tagR0 == TY_INT && tagTOS == TY_INT) {
+ o4(0xE8BD0002); // ldmfd sp!,{r1}
+ mStackUse -= 4;
+ switch(op) {
+ case OP_MUL:
+ o4(0x0E0000091); // mul r0,r1,r0
+ break;
+ case OP_DIV:
+ callRuntime((void*) runtime_DIV);
+ break;
+ case OP_MOD:
+ callRuntime((void*) runtime_MOD);
+ break;
+ case OP_PLUS:
+ o4(0xE0810000); // add r0,r1,r0
+ break;
+ case OP_MINUS:
+ o4(0xE0410000); // sub r0,r1,r0
+ break;
+ case OP_SHIFT_LEFT:
+ o4(0xE1A00011); // lsl r0,r1,r0
+ break;
+ case OP_SHIFT_RIGHT:
+ o4(0xE1A00051); // asr r0,r1,r0
+ break;
+ case OP_BIT_AND:
+ o4(0xE0010000); // and r0,r1,r0
+ break;
+ case OP_BIT_XOR:
+ o4(0xE0210000); // eor r0,r1,r0
+ break;
+ case OP_BIT_OR:
+ o4(0xE1810000); // orr r0,r1,r0
+ break;
+ case OP_BIT_NOT:
+ o4(0xE1E00000); // mvn r0, r0
+ break;
+ default:
+ error("Unimplemented op %d\n", op);
+ break;
+ }
+ popType();
+ } else {
+ Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType;
+ if (pResultType->tag == TY_DOUBLE) {
+ setupDoubleArgs();
+ switch(op) {
+ case OP_MUL:
+ callRuntime((void*) runtime_op_mul_dd);
+ break;
+ case OP_DIV:
+ callRuntime((void*) runtime_op_div_dd);
+ break;
+ case OP_PLUS:
+ callRuntime((void*) runtime_op_add_dd);
+ break;
+ case OP_MINUS:
+ callRuntime((void*) runtime_op_sub_dd);
+ break;
+ default:
+ error("Unsupported binary floating operation %d\n", op);
+ break;
+ }
+ } else {
+ setupFloatArgs();
+ switch(op) {
+ case OP_MUL:
+ callRuntime((void*) runtime_op_mul_ff);
+ break;
+ case OP_DIV:
+ callRuntime((void*) runtime_op_div_ff);
+ break;
+ case OP_PLUS:
+ callRuntime((void*) runtime_op_add_ff);
+ break;
+ case OP_MINUS:
+ callRuntime((void*) runtime_op_sub_ff);
+ break;
+ default:
+ error("Unsupported binary floating operation %d\n", op);
+ break;
+ }
+ }
+ setR0Type(pResultType);
}
- popType();
}
virtual void gUnaryCmp(int op, Type* pResultType) {
LOG_API("gUnaryCmp(%d);\n", op);
- o4(0xE3A01000); // mov r1, #0
- o4(0xE1510000); // cmp r1, r1
- switch(op) {
- case OP_LOGICAL_NOT:
- o4(0x03A00000); // moveq r0,#0
- o4(0x13A00001); // movne r0,#1
- break;
- default:
- error("Unknown unary comparison op %d", op);
- break;
+ if (op != OP_LOGICAL_NOT) {
+ error("Unknown unary cmp %d", op);
+ } else {
+ Type* pR0Type = getR0Type();
+ TypeTag tag = collapseType(pR0Type->tag);
+ switch(tag) {
+ case TY_INT:
+ o4(0xE3A01000); // mov r1, #0
+ o4(0xE1510000); // cmp r1, r1
+ o4(0x03A00000); // moveq r0,#0
+ o4(0x13A00001); // movne r0,#1
+ break;
+ case TY_FLOAT:
+ callRuntime((void*) runtime_is_zero_f);
+ break;
+ case TY_DOUBLE:
+ callRuntime((void*) runtime_is_zero_d);
+ break;
+ default:
+ error("gUnaryCmp unsupported type");
+ break;
+ }
}
setR0Type(pResultType);
}
virtual void genUnaryOp(int op) {
LOG_API("genOp(%d);\n", op);
- switch(op) {
- case OP_MINUS:
- o4(0xE3A01000); // mov r1, #0
- o4(0xE0410000); // sub r0,r1,r0
- break;
- case OP_BIT_NOT:
- o4(0xE1E00000); // mvn r0, r0
- break;
- default:
- error("Unknown unary op %d\n", op);
- break;
+ Type* pR0Type = getR0Type();
+ TypeTag tag = collapseType(pR0Type->tag);
+ switch(tag) {
+ case TY_INT:
+ switch(op) {
+ case OP_MINUS:
+ o4(0xE3A01000); // mov r1, #0
+ o4(0xE0410000); // sub r0,r1,r0
+ break;
+ case OP_BIT_NOT:
+ o4(0xE1E00000); // mvn r0, r0
+ break;
+ default:
+ error("Unknown unary op %d\n", op);
+ break;
+ }
+ break;
+ case TY_FLOAT:
+ case TY_DOUBLE:
+ switch (op) {
+ case OP_MINUS:
+ if (tag == TY_FLOAT) {
+ callRuntime((void*) runtime_op_neg_f);
+ } else {
+ callRuntime((void*) runtime_op_neg_d);
+ }
+ break;
+ case OP_BIT_NOT:
+ error("Can't apply '~' operator to a float or double.");
+ break;
+ default:
+ error("Unknown unary op %d\n", op);
+ break;
+ }
+ break;
+ default:
+ error("genUnaryOp unsupported type");
+ break;
}
}
virtual void pushR0() {
LOG_API("pushR0();\n");
- o4(0xE92D0001); // stmfd sp!,{r0}
- mStackUse += 4;
+ Type* pR0Type = getR0Type();
+ TypeTag r0ct = collapseType(pR0Type->tag);
+ if (r0ct != TY_DOUBLE) {
+ o4(0xE92D0001); // stmfd sp!,{r0}
+ mStackUse += 4;
+ } else {
+ o4(0xE92D0003); // stmfd sp!,{r0,r1}
+ mStackUse += 8;
+ }
pushType();
LOG_STACK("pushR0: %d\n", mStackUse);
}
@@ -772,20 +952,24 @@
virtual void storeR0ToTOS(Type* pPointerType) {
LOG_API("storeR0ToTOS(%d);\n", isInt);
assert(pPointerType->tag == TY_POINTER);
- o4(0xE8BD0002); // ldmfd sp!,{r1}
+ o4(0xE8BD0004); // ldmfd sp!,{r2}
+ popType();
mStackUse -= 4;
switch (pPointerType->pHead->tag) {
case TY_INT:
- o4(0xE5810000); // str r0, [r1]
+ case TY_FLOAT:
+ o4(0xE5820000); // str r0, [r2]
break;
case TY_CHAR:
- o4(0xE5C10000); // strb r0, [r1]
+ o4(0xE5C20000); // strb r0, [r2]
+ break;
+ case TY_DOUBLE:
+ o4(0xE1C200F0); // strd r0, [r2]
break;
default:
error("storeR0ToTOS: unimplemented type");
break;
}
- popType();
}
virtual void loadR0FromR0(Type* pPointerType) {
@@ -793,11 +977,15 @@
assert(pPointerType->tag == TY_POINTER);
switch (pPointerType->pHead->tag) {
case TY_INT:
+ case TY_FLOAT:
o4(0xE5900000); // ldr r0, [r0]
break;
case TY_CHAR:
o4(0xE5D00000); // ldrb r0, [r0]
break;
+ case TY_DOUBLE:
+ o4(0xE1C000D0); // ldrd r0, [r0]
+ break;
default:
error("loadR0FromR0: unimplemented type");
break;
@@ -807,7 +995,7 @@
virtual void leaR0(int ea, Type* pPointerType) {
LOG_API("leaR0(%d);\n", ea);
- if (ea < LOCAL) {
+ if (ea > -LOCAL && ea < LOCAL) {
// Local, fp relative
if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
error("Offset out of range: %08x", ea);
@@ -829,69 +1017,147 @@
virtual void storeR0(int ea, Type* pType) {
LOG_API("storeR0(%d);\n", ea);
- if (ea < LOCAL) {
- // Local, fp relative
- if (ea < -4095 || ea > 4095) {
- error("Offset out of range: %08x", ea);
- }
- if (ea < 0) {
- o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
- } else {
- o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
- }
- } else{
- // Global, absolute
- o4(0xE59F1000); // ldr r1, .L1
- o4(0xEA000000); // b .L99
- o4(ea); // .L1: .word 0
- o4(0xE5810000); // .L99: str r0, [r1]
+ TypeTag tag = pType->tag;
+ switch (tag) {
+ case TY_INT:
+ case TY_FLOAT:
+ if (ea > -LOCAL && ea < LOCAL) {
+ // Local, fp relative
+ if (ea < -4095 || ea > 4095) {
+ error("Offset out of range: %08x", ea);
+ }
+ if (ea < 0) {
+ o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
+ } else {
+ o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
+ }
+ } else{
+ // Global, absolute
+ o4(0xE59F1000); // ldr r1, .L1
+ o4(0xEA000000); // b .L99
+ o4(ea); // .L1: .word 0
+ o4(0xE5810000); // .L99: str r0, [r1]
+ }
+ break;
+ case TY_DOUBLE:
+ if ((ea & 0x7) != 0) {
+ error("double address is not aligned: %d", ea);
+ }
+ if (ea > -LOCAL && ea < LOCAL) {
+ // Local, fp relative
+ if (ea < -4095 || ea > 4095) {
+ error("Offset out of range: %08x", ea);
+ }
+ if (ea < 0) {
+ o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
+ o4(0xE50B1000 | (0xfff & (-ea + 4))); // str r1, [fp,#-ea+4]
+#if 0
+ // strd doesn't seem to work. Is encoding wrong?
+ } else if (ea < 0) {
+ o4(0xE1CB000F | ((0xff & (-ea)) << 4)); // strd r0, [fp,#-ea]
+ } else if (ea < 256) {
+ o4(0xE14B000F | ((0xff & ea) << 4)); // strd r0, [fp,#ea]
+#endif
+ } else {
+ o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
+ o4(0xE58B1000 | (0xfff & (ea + 4))); // str r1, [fp,#ea+4]
+ }
+ } else{
+ // Global, absolute
+ o4(0xE59F2000); // ldr r2, .L1
+ o4(0xEA000000); // b .L99
+ o4(ea); // .L1: .word 0
+ o4(0xE1C200F0); // .L99: strd r0, [r2]
+ }
+ break;
+ default:
+ error("Unable to store to type %d", tag);
+ break;
}
}
virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
LOG_API("loadR0(%d, %d, %d, %d);\n", ea, isIncDec, op, pType);
- if (ea < LOCAL) {
- // Local, fp relative
- if (ea < -4095 || ea > 4095) {
- error("Offset out of range: %08x", ea);
- }
- if (ea < 0) {
- o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
- } else {
- o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
- }
- } else {
- // Global, absolute
- o4(0xE59F2000); // ldr r2, .L1
- o4(0xEA000000); // b .L99
- o4(ea); // .L1: .word ea
- o4(0xE5920000); // .L99: ldr r0, [r2]
- }
+ TypeTag tag = collapseType(pType->tag);
+ switch (tag) {
+ case TY_INT:
+ case TY_FLOAT:
+ if (ea < LOCAL) {
+ // Local, fp relative
+ if (ea < -4095 || ea > 4095) {
+ error("Offset out of range: %08x", ea);
+ }
+ if (ea < 0) {
+ o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
+ } else {
+ o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
+ }
+ } else {
+ // Global, absolute
+ o4(0xE59F2000); // ldr r2, .L1
+ o4(0xEA000000); // b .L99
+ o4(ea); // .L1: .word ea
+ o4(0xE5920000); // .L99: ldr r0, [r2]
+ }
- if (isIncDec) {
- switch (op) {
- case OP_INCREMENT:
- o4(0xE2801001); // add r1, r0, #1
+ if (isIncDec) {
+ if (tag == TY_INT) {
+ switch (op) {
+ case OP_INCREMENT:
+ o4(0xE2801001); // add r1, r0, #1
+ break;
+ case OP_DECREMENT:
+ o4(0xE2401001); // sub r1, r0, #1
+ break;
+ default:
+ error("unknown opcode: %d", op);
+ }
+ if (ea < LOCAL) {
+ // Local, fp relative
+ // Don't need range check, was already checked above
+ if (ea < 0) {
+ o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
+ } else {
+ o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
+ }
+ } else{
+ // Global, absolute
+ // r2 is already set up from before.
+ o4(0xE5821000); // str r1, [r2]
+ }
+ }
+ else {
+ error("inc/dec not implemented for float.");
+ }
+ }
break;
- case OP_DECREMENT:
- o4(0xE2401001); // sub r1, r0, #1
+ case TY_DOUBLE:
+ if ((ea & 0x7) != 0) {
+ error("double address is not aligned: %d", ea);
+ }
+ if (ea < LOCAL) {
+ // Local, fp relative
+ if (ea < -4095 || ea > 4095) {
+ error("Offset out of range: %08x", ea);
+ }
+ if (ea < 0) {
+ o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
+ o4(0xE51B1000 | (0xfff & (-ea+4))); // ldr r1, [fp,#-ea+4]
+ } else {
+ o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
+ o4(0xE59B1000 | (0xfff & (ea+4))); // ldr r0, [fp,#ea+4]
+ }
+ } else {
+ // Global, absolute
+ o4(0xE59F2000); // ldr r2, .L1
+ o4(0xEA000000); // b .L99
+ o4(ea); // .L1: .word ea
+ o4(0xE1C200D0); // .L99: ldrd r0, [r2]
+ }
break;
default:
- error("unknown opcode: %d", op);
- }
- if (ea < LOCAL) {
- // Local, fp relative
- // Don't need range check, was already checked above
- if (ea < 0) {
- o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
- } else {
- o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
- }
- } else{
- // Global, absolute
- // r2 is already set up from before.
- o4(0xE5821000); // str r1, [r2]
- }
+ error("Unable to load type %d", tag);
+ break;
}
setR0Type(pType);
}
@@ -900,11 +1166,32 @@
Type* pR0Type = getR0Type();
if (bitsSame(pType, pR0Type)) {
// do nothing special
- } else if (isFloatType(pType) && isFloatType(pR0Type)) {
- // do nothing special, both held in same register on x87.
} else {
- error("Incompatible types old: %d new: %d",
- pR0Type->tag, pType->tag);
+ TypeTag r0Tag = collapseType(pR0Type->tag);
+ TypeTag destTag = collapseType(pType->tag);
+ if (r0Tag == TY_INT) {
+ if (destTag == TY_FLOAT) {
+ callRuntime((void*) runtime_int_to_float);
+ } else {
+ assert(destTag == TY_DOUBLE);
+ callRuntime((void*) runtime_int_to_double);
+ }
+ } else if (r0Tag == TY_FLOAT) {
+ if (destTag == TY_INT) {
+ callRuntime((void*) runtime_float_to_int);
+ } else {
+ assert(destTag == TY_DOUBLE);
+ callRuntime((void*) runtime_float_to_double);
+ }
+ } else {
+ assert (r0Tag == TY_DOUBLE);
+ if (destTag == TY_INT) {
+ callRuntime((void*) runtime_double_to_int);
+ } else {
+ assert(destTag == TY_FLOAT);
+ callRuntime((void*) runtime_double_to_float);
+ }
+ }
}
setR0Type(pType);
}
@@ -916,19 +1203,42 @@
virtual size_t storeR0ToArg(int l) {
LOG_API("storeR0ToArg(%d);\n", l);
- if (l < 0 || l > 4096-4) {
- error("l out of range for stack offset: 0x%08x", l);
+ Type* pR0Type = getR0Type();
+ TypeTag r0ct = collapseType(pR0Type->tag);
+ switch(r0ct) {
+ case TY_INT:
+ case TY_FLOAT:
+ if (l < 0 || l > 4096-4) {
+ error("l out of range for stack offset: 0x%08x", l);
+ }
+ o4(0xE58D0000 + l); // str r0, [sp, #l]
+ return 4;
+ case TY_DOUBLE: {
+ // Align to 8 byte boundary
+ int l2 = (l + 7) & ~7;
+ if (l2 < 0 || l2 > 4096-8) {
+ error("l out of range for stack offset: 0x%08x", l);
+ }
+ o4(0xE58D0000 + l2); // str r0, [sp, #l]
+ o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4]
+ return (l2 - l) + 8;
+ }
+ default:
+ assert(false);
+ return 0;
}
- o4(0xE58D0000 + l); // str r0, [sp, #4]
- return 4;
}
- virtual void endFunctionCallArguments(int a, int l) {
+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l);
- int argCount = l >> 2;
int argumentStackUse = l;
- if (argCount > 0) {
- int regArgCount = argCount > 4 ? 4 : argCount;
+ // Have to calculate register arg count from actual stack size,
+ // in order to properly handle ... functions.
+ int regArgCount = l >> 2;
+ if (regArgCount > 4) {
+ regArgCount = 4;
+ }
+ if (regArgCount > 0) {
argumentStackUse -= regArgCount * 4;
o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{}
}
@@ -989,10 +1299,16 @@
o4(0xE12FFF3C); // blx r12
}
- virtual void adjustStackAfterCall(int l, bool isIndirect) {
+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect);
int argCount = l >> 2;
- int stackArgs = argCount > 4 ? argCount - 4 : 0;
+ // Have to calculate register arg count from actual stack size,
+ // in order to properly handle ... functions.
+ int regArgCount = l >> 2;
+ if (regArgCount > 4) {
+ regArgCount = 4;
+ }
+ int stackArgs = argCount - regArgCount;
int stackUse = stackArgs + (isIndirect ? 1 : 0)
+ (mStackAlignmentAdjustment >> 2);
if (stackUse) {
@@ -1062,7 +1378,7 @@
/**
* alignment (in bytes) for this type of data
*/
- virtual size_t alignment(Type* pType){
+ virtual size_t alignmentOf(Type* pType){
switch(pType->tag) {
case TY_DOUBLE:
return 8;
@@ -1141,20 +1457,251 @@
return BRANCH_REL_ADDRESS_MASK & (value >> 2);
}
- typedef int (*int2FnPtr)(int a, int b);
- void callRuntime(int2FnPtr fn) {
- o4(0xE59F2000); // ldr r2, .L1
+ int calcRegArgCount(Type* pDecl) {
+ int reg = 0;
+ Type* pArgs = pDecl->pTail;
+ while (pArgs && reg < 4) {
+ Type* pArg = pArgs->pHead;
+ if ( pArg->tag == TY_DOUBLE) {
+ int evenReg = (reg + 1) & ~1;
+ if (evenReg >= 4) {
+ break;
+ }
+ reg = evenReg + 2;
+ } else {
+ reg++;
+ }
+ pArgs = pArgs->pTail;
+ }
+ return reg;
+ }
+
+ /* Pop TOS to R1
+ * Make sure both R0 and TOS are floats. (Could be ints)
+ * We know that at least one of R0 and TOS is already a float
+ */
+ void setupFloatArgs() {
+ Type* pR0Type = getR0Type();
+ Type* pTOSType = getTOSType();
+ TypeTag tagR0 = collapseType(pR0Type->tag);
+ TypeTag tagTOS = collapseType(pTOSType->tag);
+ if (tagR0 != TY_FLOAT) {
+ assert(tagR0 == TY_INT);
+ callRuntime((void*) runtime_int_to_float);
+ }
+ if (tagTOS != TY_FLOAT) {
+ assert(tagTOS == TY_INT);
+ assert(tagR0 == TY_FLOAT);
+ o4(0xE92D0001); // stmfd sp!,{r0} // push R0
+ o4(0xE59D0004); // ldr r0, [sp, #4]
+ callRuntime((void*) runtime_int_to_float);
+ o4(0xE1A01000); // mov r1, r0
+ o4(0xE8BD0001); // ldmfd sp!,{r0} // pop R0
+ o4(0xE28DD004); // add sp, sp, #4 // Pop sp
+ } else {
+ // Pop TOS
+ o4(0xE8BD0002); // ldmfd sp!,{r1}
+ }
+ mStackUse -= 4;
+ popType();
+ }
+
+ /* Pop TOS into R2..R3
+ * Make sure both R0 and TOS are doubles. Could be floats or ints.
+ * We know that at least one of R0 and TOS are already a double.
+ */
+
+ void setupDoubleArgs() {
+ Type* pR0Type = getR0Type();
+ Type* pTOSType = getTOSType();
+ TypeTag tagR0 = collapseType(pR0Type->tag);
+ TypeTag tagTOS = collapseType(pTOSType->tag);
+ if (tagR0 != TY_DOUBLE) {
+ if (tagR0 == TY_INT) {
+ callRuntime((void*) runtime_int_to_double);
+ } else {
+ assert(tagR0 == TY_FLOAT);
+ callRuntime((void*) runtime_float_to_double);
+ }
+ }
+ if (tagTOS != TY_DOUBLE) {
+ o4(0xE92D0003); // stmfd sp!,{r0,r1} // push r0,r1
+ o4(0xE59D0008); // ldr r0, [sp, #8]
+ if (tagTOS == TY_INT) {
+ callRuntime((void*) runtime_int_to_double);
+ } else {
+ assert(tagTOS == TY_FLOAT);
+ callRuntime((void*) runtime_float_to_double);
+ }
+ o4(0xE1A02000); // mov r2, r0
+ o4(0xE1A03001); // mov r3, r1
+ o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0
+ o4(0xE28DD004); // add sp, sp, #4 // Pop sp
+ mStackUse -= 4;
+ } else {
+ o4(0xE8BD000C); // ldmfd sp!,{r2,r3}
+ mStackUse -= 8;
+ }
+ popType();
+ }
+
+ void callRuntime(void* fn) {
+ o4(0xE59FC000); // ldr r12, .L1
o4(0xEA000000); // b .L99
o4((int) fn); //.L1: .word fn
- o4(0xE12FFF32); //.L99: blx r2
+ o4(0xE12FFF3C); //.L99: blx r12
}
- static int runtime_DIV(int a, int b) {
- return b / a;
+ // Integer math:
+
+ static int runtime_DIV(int b, int a) {
+ return a / b;
}
- static int runtime_MOD(int a, int b) {
- return b % a;
+ static int runtime_MOD(int b, int a) {
+ return a % b;
+ }
+
+ // Comparison to zero
+
+ static int runtime_is_non_zero_f(float a) {
+ return a != 0;
+ }
+
+ static int runtime_is_non_zero_d(double a) {
+ return a != 0;
+ }
+
+ // Comparison to zero
+
+ static int runtime_is_zero_f(float a) {
+ return a == 0;
+ }
+
+ static int runtime_is_zero_d(double a) {
+ return a == 0;
+ }
+
+ // Type conversion
+
+ static int runtime_float_to_int(float a) {
+ return (int) a;
+ }
+
+ static double runtime_float_to_double(float a) {
+ return (double) a;
+ }
+
+ static int runtime_double_to_int(double a) {
+ return (int) a;
+ }
+
+ static float runtime_double_to_float(double a) {
+ return (float) a;
+ }
+
+ static float runtime_int_to_float(int a) {
+ return (float) a;
+ }
+
+ static double runtime_int_to_double(int a) {
+ return (double) a;
+ }
+
+ // Comparisons float
+
+ static int runtime_cmp_eq_ff(float b, float a) {
+ return a == b;
+ }
+
+ static int runtime_cmp_ne_ff(float b, float a) {
+ return a != b;
+ }
+
+ static int runtime_cmp_lt_ff(float b, float a) {
+ return a < b;
+ }
+
+ static int runtime_cmp_le_ff(float b, float a) {
+ return a <= b;
+ }
+
+ static int runtime_cmp_ge_ff(float b, float a) {
+ return a >= b;
+ }
+
+ static int runtime_cmp_gt_ff(float b, float a) {
+ return a > b;
+ }
+
+ // Comparisons double
+
+ static int runtime_cmp_eq_dd(double b, double a) {
+ return a == b;
+ }
+
+ static int runtime_cmp_ne_dd(double b, double a) {
+ return a != b;
+ }
+
+ static int runtime_cmp_lt_dd(double b, double a) {
+ return a < b;
+ }
+
+ static int runtime_cmp_le_dd(double b, double a) {
+ return a <= b;
+ }
+
+ static int runtime_cmp_ge_dd(double b, double a) {
+ return a >= b;
+ }
+
+ static int runtime_cmp_gt_dd(double b, double a) {
+ return a > b;
+ }
+
+ // Math float
+
+ static float runtime_op_add_ff(float b, float a) {
+ return a + b;
+ }
+
+ static float runtime_op_sub_ff(float b, float a) {
+ return a - b;
+ }
+
+ static float runtime_op_mul_ff(float b, float a) {
+ return a * b;
+ }
+
+ static float runtime_op_div_ff(float b, float a) {
+ return a / b;
+ }
+
+ static float runtime_op_neg_f(float a) {
+ return -a;
+ }
+
+ // Math double
+
+ static double runtime_op_add_dd(double b, double a) {
+ return a + b;
+ }
+
+ static double runtime_op_sub_dd(double b, double a) {
+ return a - b;
+ }
+
+ static double runtime_op_mul_dd(double b, double a) {
+ return a * b;
+ }
+
+ static double runtime_op_div_dd(double b, double a) {
+ return a / b;
+ }
+
+ static double runtime_op_neg_d(double a) {
+ return -a;
}
static const int STACK_ALIGNMENT = 8;
@@ -1176,12 +1723,12 @@
/* returns address to patch with local variable size
*/
- virtual int functionEntry(int argCount) {
+ virtual int functionEntry(Type* pDecl) {
o(0xe58955); /* push %ebp, mov %esp, %ebp */
return oad(0xec81, 0); /* sub $xxx, %esp */
}
- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
o(0xc3c9); /* leave, ret */
*(int *) localVariableAddress = localVariableSize; /* save local variables */
}
@@ -1333,9 +1880,7 @@
error("Unsupported binary floating operation.");
break;
}
- popType();
setR0Type(pResultType);
- printf("genop: result type %d\n", pResultType->tag);
}
}
@@ -1369,7 +1914,7 @@
o(0x01f083); // xorl $1, %eax
break;
default:
- error("genUnaryCmp unsupported type");
+ error("gUnaryCmp unsupported type");
break;
}
}
@@ -1608,7 +2153,7 @@
}
}
- virtual void endFunctionCallArguments(int a, int l) {
+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
* (int*) a = l;
}
@@ -1627,7 +2172,7 @@
oad(0x2494ff, l); /* call *xxx(%esp) */
}
- virtual void adjustStackAfterCall(int l, bool isIndirect) {
+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
if (isIndirect) {
l += 4;
}
@@ -1669,13 +2214,8 @@
/**
* Alignment (in bytes) for this type of data
*/
- virtual size_t alignment(Type* pType){
- switch(pType->tag) {
- case TY_DOUBLE:
- return 8;
- default:
- return 4;
- }
+ virtual size_t alignmentOf(Type* pType){
+ return 4;
}
/**
@@ -1783,6 +2323,7 @@
o(0x58); // pop %eax
}
}
+ popType();
}
};
@@ -1812,16 +2353,16 @@
/* returns address to patch with local variable size
*/
- virtual int functionEntry(int argCount) {
- int result = mpBase->functionEntry(argCount);
- fprintf(stderr, "functionEntry(%d) -> %d\n", argCount, result);
+ virtual int functionEntry(Type* pDecl) {
+ int result = mpBase->functionEntry(pDecl);
+ fprintf(stderr, "functionEntry(pDecl) -> %d\n", result);
return result;
}
- virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) {
- fprintf(stderr, "functionExit(%d, %d, %d)\n",
- argCount, localVariableAddress, localVariableSize);
- mpBase->functionExit(argCount, localVariableAddress, localVariableSize);
+ virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
+ fprintf(stderr, "functionExit(pDecl, %d, %d)\n",
+ localVariableAddress, localVariableSize);
+ mpBase->functionExit(pDecl, localVariableAddress, localVariableSize);
}
/* load immediate value */
@@ -1915,9 +2456,9 @@
return mpBase->storeR0ToArg(l);
}
- virtual void endFunctionCallArguments(int a, int l) {
+ virtual void endFunctionCallArguments(Type* pDecl, int a, int l) {
fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l);
- mpBase->endFunctionCallArguments(a, l);
+ mpBase->endFunctionCallArguments(pDecl, a, l);
}
virtual int callForward(int symbol, Type* pFunc) {
@@ -1936,9 +2477,9 @@
mpBase->callIndirect(l, pFunc);
}
- virtual void adjustStackAfterCall(int l, bool isIndirect) {
- fprintf(stderr, "adjustStackAfterCall(%d, %d)\n", l, isIndirect);
- mpBase->adjustStackAfterCall(l, isIndirect);
+ virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) {
+ fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect);
+ mpBase->adjustStackAfterCall(pDecl, l, isIndirect);
}
virtual int jumpOffset() {
@@ -1964,8 +2505,8 @@
/**
* Alignment (in bytes) for this type of data
*/
- virtual size_t alignment(Type* pType){
- return mpBase->alignment(pType);
+ virtual size_t alignmentOf(Type* pType){
+ return mpBase->alignmentOf(pType);
}
/**
@@ -3207,15 +3748,16 @@
/* function call */
if (accept('(')) {
- Type* pArgList = NULL;
+ Type* pDecl = NULL;
VariableInfo* pVI = NULL;
if (n == 1) { // Indirect function call, push address of fn.
- pArgList = pGen->getR0Type()->pTail;
+ pDecl = pGen->getR0Type();
pGen->pushR0();
} else {
pVI = VI(t);
- pArgList = pVI->pType->pTail;
+ pDecl = pVI->pType;
}
+ Type* pArgList = pDecl->pTail;
bool varArgs = pArgList == NULL;
/* push args and invert order */
a = pGen->beginFunctionCallArguments();
@@ -3253,7 +3795,7 @@
if (! varArgs && pArgList) {
error ("Expected more argument(s). Saw %d", argCount);
}
- pGen->endFunctionCallArguments(a, l);
+ pGen->endFunctionCallArguments(pDecl, a, l);
skip(')');
if (!n) {
/* forward reference */
@@ -3265,7 +3807,7 @@
pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset(),
VI(t)->pType);
}
- pGen->adjustStackAfterCall(l, n == 1);
+ pGen->adjustStackAfterCall(pDecl, l, n == 1);
}
}
@@ -3730,8 +4272,9 @@
}
int variableAddress = 0;
addLocalSymbol(pDecl);
+ size_t alignment = pGen->alignmentOf(pDecl);
+ loc = (loc + alignment - 1) & ~ (alignment-1);
loc = loc + pGen->sizeOf(pDecl);
- loc = loc + 4;
variableAddress = -loc;
VI(pDecl->id)->pAddress = (void*) variableAddress;
if (accept('=')) {
@@ -3810,7 +4353,7 @@
for(;;) {
if (name && !name->pAddress) {
name->pAddress = (int*) allocGlobalSpace(
- pGen->alignment(name->pType),
+ pGen->alignmentOf(name->pType),
pGen->sizeOf(name->pType));
}
if (accept('=')) {
@@ -3856,16 +4399,18 @@
Type* pArg = pP->pHead;
addLocalSymbol(pArg);
/* read param name and compute offset */
+ size_t alignment = pGen->alignmentOf(pArg);
+ a = (a + alignment - 1) & ~ (alignment-1);
VI(pArg->id)->pAddress = (void*) a;
a = a + pGen->stackSizeOf(pArg);
argCount++;
}
rsym = loc = 0;
pReturnType = pDecl->pHead;
- a = pGen->functionEntry(argCount);
+ a = pGen->functionEntry(pDecl);
block(0, true);
pGen->gsym(rsym);
- pGen->functionExit(argCount, a, loc);
+ pGen->functionExit(pDecl, a, loc);
mLocals.popLevel();
}
}
diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c
index df0de93..8625cf1 100644
--- a/libacc/tests/data/float.c
+++ b/libacc/tests/data/float.c
@@ -38,13 +38,12 @@
* (float*) & f0 = 1.1f;
* (double*) & d0 = 3.3;
printf("cast lval: %g %g %g %g\n", f0, f1, d0, d1);
-
}
int main() {
printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);
printf(" ftoi(1.4f)=%d\n", ftoi(1.4f));
- printf(" dtoi(2.4f)=%d\n", dtoi(2.4f));
+ printf(" dtoi(2.4)=%d\n", dtoi(2.4));
printf(" itof(3)=%g\n", itof(3));
printf(" itod(4)=%g\n", itod(4));
testVars(1.0f, 2.0f, 3.0, 4.0);
diff --git a/libacc/tests/data/flops.c b/libacc/tests/data/flops.c
index dc36e93..7374056 100644
--- a/libacc/tests/data/flops.c
+++ b/libacc/tests/data/flops.c
@@ -4,7 +4,7 @@
// Unary ops
printf("-%g = %g\n", 1.1, -1.1);
printf("!%g = %d\n", 1.2, !1.2);
- printf("!%g = %d\n", 0.0, !0,0);
+ printf("!%g = %d\n", 0.0, !0.0);
}
void binaryOps() {
@@ -75,6 +75,7 @@
comparisonTestff(1.0f, 1.0f);
comparisonTestff(2.0f, 1.0f);
}
+
void comparisonTestid(int a, double b) {
printf("%d op %g: < %d <= %d == %d >= %d > %d != %d\n",
a, b, a < b, a <= b, a == b, a >= b, a > b, a != b);
@@ -82,9 +83,9 @@
void comparisonOpsid() {
printf("int op double:\n");
- comparisonTestid(1, 2.0f);
- comparisonTestid(1, 1.0f);
- comparisonTestid(2, 1.0f);
+ comparisonTestid(1, 2.0);
+ comparisonTestid(1, 1.0);
+ comparisonTestid(2, 1.0);
}
void comparisonTestdi(double a, int b) {
printf("%g op %d: < %d <= %d == %d >= %d > %d != %d\n",
@@ -117,10 +118,34 @@
printf("branching: %d %d %d\n", branch(-1.0), branch(0.0), branch(1.0));
}
+void testpassi(int a, int b, int c, int d, int e, int f, int g, int h) {
+ printf("testpassi: %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h);
+}
+
+void testpassf(float a, float b, float c, float d, float e, float f, float g, float h) {
+ printf("testpassf: %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h);
+}
+
+void testpassd(double a, double b, double c, double d, double e, double f, double g, double h) {
+ printf("testpassd: %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h);
+}
+
+void testpassidf(int i, double d, float f) {
+ printf("testpassidf: %d %g %g\n", i, d, f);
+}
+
+void testParameterPassing() {
+ testpassi(1, 2, 3, 4, 5, 6, 7, 8);
+ testpassf(1, 2, 3, 4, 5, 6, 7, 8);
+ testpassd(1, 2, 3, 4, 5, 6, 7, 8);
+ testpassidf(1, 2.0, 3.0f);
+}
+
int main() {
unaryOps();
binaryOps();
comparisonOps();
testBranching();
+ testParameterPassing();
return 0;
}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index 016c587..ff9af9b 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -59,8 +59,8 @@
def compare(a, b):
if a != b:
firstDiff = firstDifference(a, b)
- print "Strings differ at character %d '%s' != '%s'" % (
- firstDiff, safeAccess(a, firstDiff), safeAccess(b, firstDiff))
+ print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % (
+ firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff))
def safeAccess(s, i):
if 0 <= i < len(s):
@@ -97,7 +97,7 @@
self.compileCheck(["-R", "data/returnval-ansi.c"],
"Executing compiled code:\nresult: 42\n")
- def testStingLiteralConcatenation(self):
+ def testStringLiteralConcatenation(self):
self.compileCheck(["-R", "data/testStringConcat.c"],
"Executing compiled code:\nresult: 13\n", "Hello, world\n")
@@ -115,6 +115,69 @@
"0 = 0\n010 = 8\n0x10 = 16\n'\\a' = 7\n'\\b' = 8\n'\\f' = 12\n'\\n' = 10\n'\\r' = 13\n'\\t' = 9\n'\\v' = 11\n'\\\\' = 92\n'\\'' = 39\n" +
"'\\\"' = 34\n'\\?' = 63\n'\\0' = 0\n'\\1' = 1\n'\\12' = 10\n'\\123' = 83\n'\\x0' = 0\n'\\x1' = 1\n'\\x12' = 18\n'\\x123' = 291\n'\\x1f' = 31\n'\\x1F' = 31\n")
+ def testRunFloat(self):
+ self.compileCheck(["-R", "data/float.c"],
+ "Executing compiled code:\nresult: 0\n",
+ "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")
+
+ def testRunFlops(self):
+ self.compileCheck(["-R", "data/flops.c"],
+ "Executing compiled code:\nresult: 0\n",
+ "-1.1 = -1.1\n" +
+ "!1.2 = 0\n" +
+ "!0 = 1\n" +
+ "double op double:\n" +
+ "1 + 2 = 3\n" +
+ "1 - 2 = -1\n" +
+ "1 * 2 = 2\n" +
+ "1 / 2 = 0.5\n" +
+ "float op float:\n" +
+ "1 + 2 = 3\n" +
+ "1 - 2 = -1\n" +
+ "1 * 2 = 2\n" +
+ "1 / 2 = 0.5\n" +
+ "double op float:\n" +
+ "1 + 2 = 3\n" +
+ "1 - 2 = -1\n" +
+ "1 * 2 = 2\n" +
+ "1 / 2 = 0.5\n" +
+ "double op int:\n" +
+ "1 + 2 = 3\n" +
+ "1 - 2 = -1\n" +
+ "1 * 2 = 2\n" +
+ "1 / 2 = 0.5\n" +
+ "int op double:\n" +
+ "1 + 2 = 3\n" +
+ "1 - 2 = -1\n" +
+ "1 * 2 = 2\n" +
+ "1 / 2 = 0.5\n" +
+ "double op double:\n" +
+ "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
+ "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
+ "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
+ "double op float:\n" +
+ "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
+ "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
+ "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
+ "float op float:\n" +
+ "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
+ "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
+ "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
+ "int op double:\n" +
+ "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
+ "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
+ "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
+ "double op int:\n" +
+ "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
+ "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
+ "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
+ "branching: 1 0 1\n" +
+ "testpassi: 1 2 3 4 5 6 7 8\n" +
+ "testpassf: 1 2 3 4 5 6 7 8\n" +
+ "testpassd: 1 2 3 4 5 6 7 8\n" +
+ "testpassidf: 1 2 3\n"
+ )
+
def testArmRunReturnVal(self):
self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"],
"Executing compiled code:\nresult: 42\n")
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 88635d9..bde336f 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -224,6 +224,16 @@
return result;
}
+int ifc_enable(const char *ifname)
+{
+ int result;
+
+ ifc_init();
+ result = ifc_up(ifname);
+ ifc_close();
+ return result;
+}
+
int ifc_disable(const char *ifname)
{
int result;