요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
Notes
=====
There seems to be a problem with exp(double) and our emulator. I haven't
been able to track it down yet. This does not occur with the emulator
supplied by Russell King.
I also found one oddity in the emulator. I don't think it is serious but
will point it out. The ARM calling conventions require floating point
registers f4-f7 to be preserved over a function call. The compiler quite
often uses an stfe instruction to save f4 on the stack upon entry to a
function, and an ldfe instruction to restore it before returning.
I was looking at some code, that calculated a double result, stored it in f4
then made a function call. Upon return from the function call the number in
f4 had been converted to an extended value in the emulator.
This is a side effect of the stfe instruction. The double in f4 had to be
converted to extended, then stored. If an lfm/sfm combination had been used,
then no conversion would occur. This has performance considerations. The
result from the function call and f4 were used in a multiplication. If the
emulator sees a multiply of a double and extended, it promotes the double to
extended, then does the multiply in extended precision.
This code will cause this problem:
double x, y, z;
z = log(x)/log(y);
The result of log(x) (a double) will be calculated, returned in f0, then
moved to f4 to preserve it over the log(y) call. The division will be done
in extended precision, due to the stfe instruction used to save f4 in log(y).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Notes
1-7이 emulator에는 `exp(double)` 관련 문제가 있는 것으로 보이며 아직 원인을 찾지 못했습니다. Russell King이 제공한 emulator에서는 같은 문제가 발생하지 않습니다.
stfe precision conversion
8-24ARM calling convention은 function call을 지나도 floating-point register `f4`~`f7`을 보존하도록 요구합니다. compiler는 function 진입 때 `stfe`로 `f4`를 stack에 저장하고 return 전에 `ldfe`로 복원하는 경우가 많습니다.
double 결과를 `f4`에 넣고 function을 호출한 code를 조사했을 때, return 후 emulator 안의 `f4` 값이 extended value로 바뀌어 있었습니다.
이는 `stfe`의 side effect입니다. `f4`의 double을 extended로 변환한 뒤 저장하기 때문입니다. `lfm`/`sfm` 조합을 썼다면 변환이 일어나지 않습니다. 이후 double과 extended를 multiply하면 emulator가 double을 extended로 promote한 뒤 extended precision으로 연산하므로 성능에도 영향을 줍니다.
Precision promotion example
25-32다음 code가 이 문제를 일으킵니다.
double x, y, z;
z = log(x)/log(y);
`log(x)`의 double 결과는 `f0`으로 반환된 뒤 `log(y)` call 동안 보존하려고 `f4`로 이동합니다. `log(y)`가 `f4`를 저장할 때 사용한 `stfe` 때문에 최종 division은 extended precision으로 수행됩니다.
요약과 해설
notes.rst:1-32register 보존 자체는 ABI를 지키지만 저장 instruction이 precision을 바꾸면 복원 뒤 연산의 type promotion까지 달라집니다. 문제는 값 하나가 아니라 호출 경계를 넘는 data representation입니다.
double 결과가 function-call save/restore를 거치며 extended로 승격됩니다.