MultiU16X8toH16とMultiU24X24toH16の解析 その2

戦略
1. アセンブラと同じ操作をするCコードをline by lineで書いてみる
2. Sprinterを実際に動かして、入力値と出力値を調べる


解析用Arduinoプログラム

// intRes = intIn1 * intIn2 >> 16
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
#define Hoge(intRes, charIn1, intIn2) \
asm volatile ( \
	"clr r26 \n\t" \
	"mul %A1, %B2 \n\t" \
	"movw %A0, r0 \n\t" \	
	"mul %A1, %A2 \n\t" \
	"add %A0, r1 \n\t" \
	"adc %B0, r26 \n\t" \
	"lsr r0 \n\t" \
	"adc %A0, r26 \n\t" \
	"adc %B0, r26 \n\t" \
	"clr r1 \n\t" \
	: \
	"=&r" (intRes) \
	: \
	"d" (charIn1), \
	"d" (intIn2) \
	: \
	"r26" \
	)

// intRes = longIn1 * longIn2 >> 24
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 48bit result
#define Foo(intRes, longIn1, longIn2) \
asm volatile ( \
	"clr r26 \n\t" \
	"mul %A1, %B2 \n\t" \
	"mov r27, r1 \n\t" \
	"mul %B1, %C2 \n\t" \
	"movw %A0, r0 \n\t" \
	"mul %C1, %C2 \n\t" \
	"add %B0, r0 \n\t" \
	"mul %C1, %B2 \n\t" \
	"add %A0, r0 \n\t" \
	"adc %B0, r1 \n\t" \
	"mul %A1, %C2 \n\t" \
	"add r27, r0 \n\t" \
	"adc %A0, r1 \n\t" \
	"adc %B0, r26 \n\t" \
	"mul %B1, %B2 \n\t" \
	"add r27, r0 \n\t" \
	"adc %A0, r1 \n\t" \
	"adc %B0, r26 \n\t" \
	"mul %C1, %A2 \n\t" \
	"add r27, r0 \n\t" \
	"adc %A0, r1 \n\t" \
	"adc %B0, r26 \n\t" \
	"mul %B1, %A2 \n\t" \
	"add r27, r1 \n\t" \
	"adc %A0, r26 \n\t" \
	"adc %B0, r26 \n\t" \
	"lsr r27 \n\t" \
	"adc %A0, r26 \n\t" \
	"adc %B0, r26 \n\t" \
	"clr r1 \n\t" \
	: \
	"=&r" (intRes) \
	: \
	"d" (longIn1), \
	"d" (longIn2) \
	: \
	"r26" , "r27" \
	)

int timer;
int timer2;
uint8_t tmp_step_rate;
uint8_t tmp_step_rate2;
int  gain;
int  gain2;
// int acc_step_rate;
// long acceleration_time;
// long acceleration_rate;

void setVar(){
	timer = 0;
	// tmp_step_rate = tmp_step_rate2 = B01001111; //8bit
	// gain = gain2 = (B01001111 * 256) + B00001111;//16bit
	tmp_step_rate = tmp_step_rate2 = 247; //8bit
	gain = gain2 = 117;//16bit
}

void setup() {
  // put your setup code here, to run once:
	Serial.begin(115200);

	//-----------------------------------
	Serial.println("******");
	// tmp_step_rate2 = B01111111; //8bit
	// gain2 = (B01111111 * 256) + B01111111;//16bit
	setVar();
	Hoge(timer2, tmp_step_rate2, gain2);
	Serial.println("A*B >> 16 (ASM)");
	printBits(timer2>>8);printBits(timer2);
	Serial.println();
	Serial.println(timer2,DEC);
	Serial.println("******");
	//-----------------------------------

	//-----------------------------------
	// assembler line-by-line emulation
	uint8_t r26 = 0;
	uint8_t a0,b0;    // output
	uint8_t a1,a2,b2; //input
	a1 = tmp_step_rate;
	a2 = gain;
    b2 = gain >> 8;
    int r1r0 = (int)a1*(int)b2;
    uint8_t r1 = r1r0 >> 8;
    uint8_t r0 = r1r0;
    a0 = r0;
    r1r0 = (int)a1*(int)a2;
    r1 = r1r0 >> 8;
    r0 = r1r0;
    a0 = a0 + r1;
    b0 = r26;
    r0 = r0 >> 1;
    a0 = a0 + r26;
    b0 = b0 + r26;
    r1 = 0;
    int result = (b0<<8) + a0;
    printBits(b0);printBits(a0); 
    Serial.println();
    Serial.println(result,DEC);

	//-----------------------------------

	//-----------------------------------
	// tmp_step_rate = 0x0F; //8bit
	// gain = 0x0002;//16bit
	Serial.println("******");
	setVar();
	Serial.print("tmp_step_rate: ");Serial.print(tmp_step_rate,DEC);Serial.print(" ");printBits(tmp_step_rate);
	Serial.println();

	Serial.print("gain: ");Serial.print(gain);Serial.print(" ");
	printBits(gain/256);
	printBits(gain%256);
	Serial.println();

	long hoge = ((long) tmp_step_rate * (long) gain); //32bit
	Serial.print(tmp_step_rate,DEC);
	Serial.print("x");
	Serial.print(gain,DEC);
	Serial.print("=");
	Serial.println(hoge);
	Serial.print("Full bits: ");
	printBits(hoge >> 16);
	printBits(hoge >> 8);
	printBits(hoge);
	Serial.println();
	char moge = (hoge) >> 16;
	Serial.print(">>16 bits shift: ");
	printBits(moge>>8);printBits(moge);
	Serial.println();
	Serial.println(moge,DEC);
	Serial.println("******");
	//-----------------------------------

	// acceleration_time = 0x00000001 ; //32bit
	// acceleration_rate = 0x00000001 ; //32bit
	// Serial.println("compute2");
	// Foo(acc_step_rate, acceleration_time, acceleration_time);
	// Serial.println(acceleration_time); 
	// Serial.println(acceleration_rate); 
	// Serial.println(acc_step_rate);

}

void printBits(byte myByte){
 for(byte mask = 0x80; mask; mask >>= 1){
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void loop() {
  // put your main code here, to run repeatedly:

}