Work around a bug in the Tru64 5.1 assembler (divq with immediate arguments)

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@3673 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
master
Xavier Leroy 2001-08-28 08:44:20 +00:00
parent dbd7e48bb3
commit 667846e97e
1 changed files with 36 additions and 22 deletions

View File

@ -516,28 +516,42 @@ let emit_instr fallthrough i =
| Lop(Iintop op) ->
let instr = name_for_int_operation op in
` {emit_string instr} {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
| Lop(Iintop_imm(Idiv, n)) when n = 1 lsl (Misc.log2 n) ->
let l = Misc.log2 n in
if is_immediate n then
` addq {emit_reg i.arg.(0)}, {emit_int(n-1)}, $25\n`
else begin
` ldiq $25, {emit_int(n-1)}\n`;
` addq {emit_reg i.arg.(0)}, $25, $25\n`
end;
` cmovge {emit_reg i.arg.(0)}, {emit_reg i.arg.(0)}, $25\n`;
` sra $25, {emit_int l}, {emit_reg i.res.(0)}\n`
| Lop(Iintop_imm(Imod, n)) when n = 1 lsl (Misc.log2 n) ->
let l = Misc.log2 n in
if is_immediate n then
` and {emit_reg i.arg.(0)}, {emit_int(n-1)}, $25\n`
else begin
` ldiq $25, {emit_int (n-1)}\n`;
` and {emit_reg i.arg.(0)}, $25, $25\n`
end;
` subq $25, {emit_int n}, $24\n`;
` cmovge {emit_reg i.arg.(0)}, $25, $24\n`;
` cmoveq $25, $25, $24\n`;
` mov $24, {emit_reg i.res.(0)}\n`
| Lop(Iintop_imm(Idiv, n)) ->
if n = 1 lsl (Misc.log2 n) then begin
let l = Misc.log2 n in
if is_immediate n then
` addq {emit_reg i.arg.(0)}, {emit_int(n-1)}, $25\n`
else begin
` ldiq $25, {emit_int(n-1)}\n`;
` addq {emit_reg i.arg.(0)}, $25, $25\n`
end;
` cmovge {emit_reg i.arg.(0)}, {emit_reg i.arg.(0)}, $25\n`;
` sra $25, {emit_int l}, {emit_reg i.res.(0)}\n`
end else begin
(* divq with immediate arg is incorrectly assembled in Tru64 5.1,
so emulate it ourselves *)
` ldiq $25, {emit_int n}\n`;
` divq {emit_reg i.arg.(0)}, $25, {emit_reg i.res.(0)}\n`
end
| Lop(Iintop_imm(Imod, n)) ->
if n = 1 lsl (Misc.log2 n) then begin
let l = Misc.log2 n in
if is_immediate n then
` and {emit_reg i.arg.(0)}, {emit_int(n-1)}, $25\n`
else begin
` ldiq $25, {emit_int (n-1)}\n`;
` and {emit_reg i.arg.(0)}, $25, $25\n`
end;
` subq $25, {emit_int n}, $24\n`;
` cmovge {emit_reg i.arg.(0)}, $25, $24\n`;
` cmoveq $25, $25, $24\n`;
` mov $24, {emit_reg i.res.(0)}\n`
end else begin
(* remq with immediate arg is incorrectly assembled in Tru64 5.1,
so emulate it ourselves *)
` ldiq $25, {emit_int n}\n`;
` remq {emit_reg i.arg.(0)}, $25, {emit_reg i.res.(0)}\n`
end
| Lop(Iintop_imm(Ilsl, 1)) ->
(* Turn x << 1 into x + x, slightly faster according to the docs *)
` addq {emit_reg i.arg.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`