//file "dtime.s" // Assembly language routine to convert 64-bit PowerPC TB facility to // Double-precision, floating-point number. (Plus additional routines for // testing.) CJC 981216 // Register usage: // r3 = FPU (upper 32 bits of floating point value) // r4 = FPL (lower 32 bits of floating point value) // r5 = TBU(time base upper - read from spr or loaded for test) // r6 = TBL(time base lower - read from spr or loaded for test) // r7 = leading zeroes in a register or shift count of +/-(zeroes - 11) // r8 = accumulator for final EXPonent value of DPFP number // r9 = shift count of 32 - n where n = +/-(zeroes -11) // r10 = constant register of 11 // r11 = link register storage #ifdef GCC_REGISTERS #include "gcc_registers.h" #endif /*GCC_REGISTERS */ .equ TBU,269 //Special purpose register numbers for TB .equ TBL,268 .data Local_storage: .double 0 .global Bus_speed Bus_speed: .double 16666666.67 .text .global dtime .global conversion .global get_HID1 // Routine reads the TBU and TBL. Returns seconds as double. //For CodeWarrior: //asm double dtime() dtime: mflr r11 //Save the return address. read_TB: mfspr r5,TBU //Get TBU. mfspr r6,TBL //Get TBL. mfspr r7,TBU //Get TBU again. subf. r7,r5,r7 //Did it increment between reading TBU and TBL? bgt- read_TB //If so, read them again. (Not likely) //For CodeWarrior: //asm double conversion(double TICS) conversion: cntlzw r7,r5 //Find leading zeroes in TBU. Preserve in r7. addi r9,r0,32 //Will need a 32 in several places. Create one in r9. addi r10,r0,11 //Create a constant in r10 = 11. subf. r8,r7,r9 //r8 will hold EXP. Currently (32 - leading zeroes) beq+ tbu_is_zero //TBU never got incremented? (Zeroes=32?) (Most likely) subf. r7,r10,r7 //No. Is TB more than 2^^52? (Zeroes<11?) r7 = (Z-11) add r8,r8,r9 //Final exponent will be (64 - 1 - leading zeroes). bge+ tbu_lt_8yrs //If TB>2^^52, shift TBU bits right. (Not likely) tbu_gt_8yrs: //for Z<11: fpu = tbu>>n=(11-Z); //fpl = tbu<>n=(11-Z); neg r7,r7 //rlwnm shift count of (11-Z) = -(Z-11) = n = r7. subf r9,r7,r9 //rlwnm shift count of 32-n = 32 - (11-Z) = r9. rlwnm r3,r5,r9,12,31 //Shift TBU right n = (11 - Z). Mask off [0:11]. rlwnm r4,r5,r9,0,10 //Shift remaining TBU bits left n = 32-(11-Z) rlwnm r6,r6,r9,0,31 //Shift TBL right n = (11 - Z) or r4,r6,r4 //Or rest of TBU shifted left with TBL shifted right. b form_exponent //Go bias the exponent and or into FPU. tbu_lt_8yrs: //for Z>=11: fpu=tbu<>n=(32-(Z-11)); //fpl=tbl<>n=(11-z); fpl = tbl<=11: fpu = tbl<<(z-11); fpl = 0; rlwnm r3,r6,r7,12,31 //Shift TBL left n = (Z-11). Mask off bits 0-11. xor r4,r4,r4 //fpl = 0. b form_exponent tbl_is_zero: //for Z=32 && z=32: fpu = fpl = 0; xor r3,r3,r3 //Unlikely result that TB was zero. Prepare to xor r4,r4,r4 //return all zeroes for the floating point value. b compute_seconds form_exponent: addi r8,r8,1022 //Add DP bias (1023) -1 to the exponent rlwinm r8,r8,20,1,12 //Biased DP EXP will be (63-(leading zeroes in TB)+1023). or r3,r3,r8 compute_seconds: lis r5, Local_storage@h ori r5, r5, Local_storage@l stw r3, 0(r5) stw r4, 4(r5) lfd f2, 0(r5) //Load back in as 64bit float lfd f1, 8(r5) //Get Bus_speed to divide with fdiv f1,f2,f1 //Divide by bus clock ticks per second mtlr r11 blr //Return time in seconds as double in fp1 // Routine reads the HID1 (PLL_CFG) register. Returns in r3. get_HID1: mfspr r3,1009 //Get HID1 register. blr