ra386int.pas 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
  4. Does the parsing process for the intel styled inline assembler.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit Ra386int;
  19. {$i fpcdefs.inc}
  20. Interface
  21. uses
  22. node;
  23. function assemble: tnode;
  24. Implementation
  25. uses
  26. { common }
  27. cutils,cclasses,
  28. { global }
  29. globtype,globals,verbose,
  30. systems,
  31. { aasm }
  32. cpuinfo,cpubase,aasmbase,aasmtai,aasmcpu,
  33. { symtable }
  34. symconst,symbase,symtype,symsym,symtable,
  35. { pass 1 }
  36. nbas,
  37. { parser }
  38. scanner,
  39. { register allocator }
  40. rautils,rax86,itx86int,
  41. { codegen }
  42. rgobj,cgbase,cgobj,procinfo
  43. ;
  44. type
  45. tasmtoken = (
  46. AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
  47. AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
  48. AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
  49. AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,
  50. {------------------ Assembler directives --------------------}
  51. AS_DB,AS_DW,AS_DD,AS_END,
  52. {------------------ Assembler Operators --------------------}
  53. AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_NEAR,AS_FAR,
  54. AS_HIGH,AS_LOW,AS_OFFSET,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
  55. AS_AND,AS_OR,AS_XOR);
  56. tasmkeyword = string[6];
  57. const
  58. { These tokens should be modified accordingly to the modifications }
  59. { in the different enumerations. }
  60. firstdirective = AS_DB;
  61. lastdirective = AS_END;
  62. firstoperator = AS_BYTE;
  63. lastoperator = AS_XOR;
  64. _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  65. _count_asmoperators = longint(lastoperator)-longint(firstoperator);
  66. _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  67. ('DB','DW','DD','END');
  68. { problems with shl,shr,not,and,or and xor, they are }
  69. { context sensitive. }
  70. _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
  71. 'BYTE','WORD','DWORD','QWORD','TBYTE','NEAR','FAR','HIGH',
  72. 'LOW','OFFSET','SEG','TYPE','PTR','MOD','SHL','SHR','NOT','AND',
  73. 'OR','XOR');
  74. token2str : array[tasmtoken] of string[10] = (
  75. '','Label','LLabel','String','Integer',
  76. ',','[',']','(',
  77. ')',':','.','+','-','*',
  78. ';','identifier','register','opcode','/',
  79. '','','','END',
  80. '','','','','','','','',
  81. '','','','type','ptr','mod','shl','shr','not',
  82. 'and','or','xor'
  83. );
  84. const
  85. newline = #10;
  86. firsttoken : boolean = TRUE;
  87. var
  88. _asmsorted : boolean;
  89. inexpression : boolean;
  90. curlist : TAAsmoutput;
  91. c : char;
  92. prevasmtoken : tasmtoken;
  93. actasmtoken : tasmtoken;
  94. actasmpattern : string;
  95. actasmregister : tregister;
  96. actopcode : tasmop;
  97. actopsize : topsize;
  98. actcondition : tasmcond;
  99. iasmops : tdictionary;
  100. Procedure SetupTables;
  101. { creates uppercased symbol tables for speed access }
  102. var
  103. i : tasmop;
  104. str2opentry: tstr2opentry;
  105. Begin
  106. { opcodes }
  107. iasmops:=tdictionary.create;
  108. iasmops.delete_doubles:=true;
  109. for i:=firstop to lastop do
  110. begin
  111. str2opentry:=tstr2opentry.createname(upper(std_op2str[i]));
  112. str2opentry.op:=i;
  113. iasmops.insert(str2opentry);
  114. end;
  115. end;
  116. {---------------------------------------------------------------------}
  117. { Routines for the tokenizing }
  118. {---------------------------------------------------------------------}
  119. function is_asmopcode(const s: string):boolean;
  120. var
  121. str2opentry: tstr2opentry;
  122. cond : string[4];
  123. cnd : tasmcond;
  124. j: longint;
  125. Begin
  126. is_asmopcode:=FALSE;
  127. actopcode:=A_None;
  128. actcondition:=C_None;
  129. actopsize:=S_NO;
  130. str2opentry:=tstr2opentry(iasmops.search(s));
  131. if assigned(str2opentry) then
  132. begin
  133. actopcode:=str2opentry.op;
  134. actasmtoken:=AS_OPCODE;
  135. is_asmopcode:=TRUE;
  136. exit;
  137. end;
  138. { not found yet, check condition opcodes }
  139. j:=0;
  140. while (j<CondAsmOps) do
  141. begin
  142. if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
  143. begin
  144. cond:=Copy(s,Length(CondAsmOpStr[j])+1,255);
  145. if cond<>'' then
  146. begin
  147. for cnd:=low(TasmCond) to high(TasmCond) do
  148. if Cond=Upper(cond2str[cnd]) then
  149. begin
  150. actopcode:=CondASmOp[j];
  151. actcondition:=cnd;
  152. is_asmopcode:=TRUE;
  153. actasmtoken:=AS_OPCODE;
  154. exit
  155. end;
  156. end;
  157. end;
  158. inc(j);
  159. end;
  160. end;
  161. function is_asmoperator(const s: string):boolean;
  162. var
  163. i : longint;
  164. Begin
  165. for i:=0 to _count_asmoperators do
  166. if s=_asmoperators[i] then
  167. begin
  168. actasmtoken:=tasmtoken(longint(firstoperator)+i);
  169. is_asmoperator:=true;
  170. exit;
  171. end;
  172. is_asmoperator:=false;
  173. end;
  174. Function is_asmdirective(const s: string):boolean;
  175. var
  176. i : longint;
  177. Begin
  178. for i:=0 to _count_asmdirectives do
  179. if s=_asmdirectives[i] then
  180. begin
  181. actasmtoken:=tasmtoken(longint(firstdirective)+i);
  182. is_asmdirective:=true;
  183. exit;
  184. end;
  185. is_asmdirective:=false;
  186. end;
  187. function is_register(const s:string):boolean;
  188. begin
  189. is_register:=false;
  190. actasmregister:=masm_regnum_search(lower(s));
  191. if actasmregister<>NR_NO then
  192. begin
  193. is_register:=true;
  194. actasmtoken:=AS_REGISTER;
  195. end;
  196. end;
  197. function is_locallabel(const s:string):boolean;
  198. begin
  199. is_locallabel:=(length(s)>1) and (s[1]='@');
  200. end;
  201. Procedure GetToken;
  202. var
  203. len : longint;
  204. forcelabel : boolean;
  205. srsym : tsym;
  206. srsymtable : tsymtable;
  207. begin
  208. { save old token and reset new token }
  209. prevasmtoken:=actasmtoken;
  210. actasmtoken:=AS_NONE;
  211. { reset }
  212. forcelabel:=FALSE;
  213. actasmpattern:='';
  214. { while space and tab , continue scan... }
  215. while (c in [' ',#9]) do
  216. c:=current_scanner.asmgetchar;
  217. { get token pos }
  218. if not (c in [newline,#13,'{',';']) then
  219. current_scanner.gettokenpos;
  220. { Local Label, Label, Directive, Prefix or Opcode }
  221. if firsttoken and not (c in [newline,#13,'{',';']) then
  222. begin
  223. firsttoken:=FALSE;
  224. len:=0;
  225. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  226. begin
  227. { if there is an at_sign, then this must absolutely be a label }
  228. if c = '@' then
  229. forcelabel:=TRUE;
  230. inc(len);
  231. actasmpattern[len]:=c;
  232. c:=current_scanner.asmgetchar;
  233. end;
  234. actasmpattern[0]:=chr(len);
  235. uppervar(actasmpattern);
  236. { label ? }
  237. if c = ':' then
  238. begin
  239. if actasmpattern[1]='@' then
  240. actasmtoken:=AS_LLABEL
  241. else
  242. actasmtoken:=AS_LABEL;
  243. { let us point to the next character }
  244. c:=current_scanner.asmgetchar;
  245. firsttoken:=true;
  246. exit;
  247. end;
  248. { Are we trying to create an identifier with }
  249. { an at-sign...? }
  250. if forcelabel then
  251. Message(asmr_e_none_label_contain_at);
  252. { opcode ? }
  253. If is_asmopcode(actasmpattern) then
  254. Begin
  255. { check if we are in an expression }
  256. { then continue with asm directives }
  257. if not inexpression then
  258. exit;
  259. end;
  260. if is_asmdirective(actasmpattern) then
  261. exit;
  262. message1(asmr_e_unknown_opcode,actasmpattern);
  263. actasmtoken:=AS_NONE;
  264. exit;
  265. end
  266. else { else firsttoken }
  267. begin
  268. case c of
  269. '@' : { possiblities : - local label reference , such as in jmp @local1 }
  270. { - @Result, @Code or @Data special variables. }
  271. begin
  272. actasmpattern:=c;
  273. c:=current_scanner.asmgetchar;
  274. while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
  275. begin
  276. actasmpattern:=actasmpattern + c;
  277. c:=current_scanner.asmgetchar;
  278. end;
  279. uppervar(actasmpattern);
  280. actasmtoken:=AS_ID;
  281. exit;
  282. end;
  283. 'A'..'Z','a'..'z','_': { identifier, register, opcode, prefix or directive }
  284. begin
  285. actasmpattern:=c;
  286. c:=current_scanner.asmgetchar;
  287. while c in ['A'..'Z','a'..'z','0'..'9','_'] do
  288. begin
  289. actasmpattern:=actasmpattern + c;
  290. c:=current_scanner.asmgetchar;
  291. end;
  292. uppervar(actasmpattern);
  293. { after prefix we allow also a new opcode }
  294. If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
  295. Begin
  296. { if we are not in a constant }
  297. { expression than this is an }
  298. { opcode. }
  299. if not inexpression then
  300. exit;
  301. end;
  302. { support st(X) for fpu registers }
  303. if (actasmpattern = 'ST') and (c='(') then
  304. Begin
  305. actasmpattern:=actasmpattern+c;
  306. c:=current_scanner.asmgetchar;
  307. if c in ['0'..'7'] then
  308. actasmpattern:=actasmpattern + c
  309. else
  310. Message(asmr_e_invalid_fpu_register);
  311. c:=current_scanner.asmgetchar;
  312. if c <> ')' then
  313. Message(asmr_e_invalid_fpu_register)
  314. else
  315. Begin
  316. actasmpattern:=actasmpattern + c;
  317. c:=current_scanner.asmgetchar;
  318. end;
  319. end;
  320. if is_register(actasmpattern) then
  321. exit;
  322. if is_asmdirective(actasmpattern) then
  323. exit;
  324. if is_asmoperator(actasmpattern) then
  325. exit;
  326. { if next is a '.' and this is a unitsym then we also need to
  327. parse the identifier }
  328. if (c='.') then
  329. begin
  330. searchsym(actasmpattern,srsym,srsymtable);
  331. if assigned(srsym) and
  332. (srsym.typ=unitsym) and
  333. (srsym.owner.unitid=0) then
  334. begin
  335. actasmpattern:=actasmpattern+c;
  336. c:=current_scanner.asmgetchar;
  337. while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
  338. begin
  339. actasmpattern:=actasmpattern + upcase(c);
  340. c:=current_scanner.asmgetchar;
  341. end;
  342. end;
  343. end;
  344. actasmtoken:=AS_ID;
  345. exit;
  346. end;
  347. '''' : { string or character }
  348. begin
  349. actasmpattern:='';
  350. current_scanner.in_asm_string:=true;
  351. repeat
  352. if c = '''' then
  353. begin
  354. c:=current_scanner.asmgetchar;
  355. if c=newline then
  356. begin
  357. Message(scan_f_string_exceeds_line);
  358. break;
  359. end;
  360. repeat
  361. if c='''' then
  362. begin
  363. c:=current_scanner.asmgetchar;
  364. if c='''' then
  365. begin
  366. actasmpattern:=actasmpattern+'''';
  367. c:=current_scanner.asmgetchar;
  368. if c=newline then
  369. begin
  370. Message(scan_f_string_exceeds_line);
  371. break;
  372. end;
  373. end
  374. else
  375. break;
  376. end
  377. else
  378. begin
  379. actasmpattern:=actasmpattern+c;
  380. c:=current_scanner.asmgetchar;
  381. if c=newline then
  382. begin
  383. Message(scan_f_string_exceeds_line);
  384. break
  385. end;
  386. end;
  387. until false; { end repeat }
  388. end
  389. else
  390. break; { end if }
  391. until false;
  392. current_scanner.in_asm_string:=false;
  393. actasmtoken:=AS_STRING;
  394. exit;
  395. end;
  396. '"' : { string or character }
  397. begin
  398. current_scanner.in_asm_string:=true;
  399. actasmpattern:='';
  400. repeat
  401. if c = '"' then
  402. begin
  403. c:=current_scanner.asmgetchar;
  404. if c=newline then
  405. begin
  406. Message(scan_f_string_exceeds_line);
  407. break;
  408. end;
  409. repeat
  410. if c='"' then
  411. begin
  412. c:=current_scanner.asmgetchar;
  413. if c='"' then
  414. begin
  415. actasmpattern:=actasmpattern+'"';
  416. c:=current_scanner.asmgetchar;
  417. if c=newline then
  418. begin
  419. Message(scan_f_string_exceeds_line);
  420. break;
  421. end;
  422. end
  423. else
  424. break;
  425. end
  426. else
  427. begin
  428. actasmpattern:=actasmpattern+c;
  429. c:=current_scanner.asmgetchar;
  430. if c=newline then
  431. begin
  432. Message(scan_f_string_exceeds_line);
  433. break
  434. end;
  435. end;
  436. until false; { end repeat }
  437. end
  438. else
  439. break; { end if }
  440. until false;
  441. current_scanner.in_asm_string:=false;
  442. actasmtoken:=AS_STRING;
  443. exit;
  444. end;
  445. '$' :
  446. begin
  447. c:=current_scanner.asmgetchar;
  448. while c in ['0'..'9','A'..'F','a'..'f'] do
  449. begin
  450. actasmpattern:=actasmpattern + c;
  451. c:=current_scanner.asmgetchar;
  452. end;
  453. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  454. actasmtoken:=AS_INTNUM;
  455. exit;
  456. end;
  457. ',' :
  458. begin
  459. actasmtoken:=AS_COMMA;
  460. c:=current_scanner.asmgetchar;
  461. exit;
  462. end;
  463. '[' :
  464. begin
  465. actasmtoken:=AS_LBRACKET;
  466. c:=current_scanner.asmgetchar;
  467. exit;
  468. end;
  469. ']' :
  470. begin
  471. actasmtoken:=AS_RBRACKET;
  472. c:=current_scanner.asmgetchar;
  473. exit;
  474. end;
  475. '(' :
  476. begin
  477. actasmtoken:=AS_LPAREN;
  478. c:=current_scanner.asmgetchar;
  479. exit;
  480. end;
  481. ')' :
  482. begin
  483. actasmtoken:=AS_RPAREN;
  484. c:=current_scanner.asmgetchar;
  485. exit;
  486. end;
  487. ':' :
  488. begin
  489. actasmtoken:=AS_COLON;
  490. c:=current_scanner.asmgetchar;
  491. exit;
  492. end;
  493. '.' :
  494. begin
  495. actasmtoken:=AS_DOT;
  496. c:=current_scanner.asmgetchar;
  497. exit;
  498. end;
  499. '+' :
  500. begin
  501. actasmtoken:=AS_PLUS;
  502. c:=current_scanner.asmgetchar;
  503. exit;
  504. end;
  505. '-' :
  506. begin
  507. actasmtoken:=AS_MINUS;
  508. c:=current_scanner.asmgetchar;
  509. exit;
  510. end;
  511. '*' :
  512. begin
  513. actasmtoken:=AS_STAR;
  514. c:=current_scanner.asmgetchar;
  515. exit;
  516. end;
  517. '/' :
  518. begin
  519. actasmtoken:=AS_SLASH;
  520. c:=current_scanner.asmgetchar;
  521. exit;
  522. end;
  523. '0'..'9':
  524. begin
  525. actasmpattern:=c;
  526. c:=current_scanner.asmgetchar;
  527. { Get the possible characters }
  528. while c in ['0'..'9','A'..'F','a'..'f'] do
  529. begin
  530. actasmpattern:=actasmpattern + c;
  531. c:=current_scanner.asmgetchar;
  532. end;
  533. { Get ending character }
  534. uppervar(actasmpattern);
  535. c:=upcase(c);
  536. { possibly a binary number. }
  537. if (actasmpattern[length(actasmpattern)] = 'B') and (c <> 'H') then
  538. Begin
  539. { Delete the last binary specifier }
  540. delete(actasmpattern,length(actasmpattern),1);
  541. actasmpattern:=tostr(ValBinary(actasmpattern));
  542. actasmtoken:=AS_INTNUM;
  543. exit;
  544. end
  545. else
  546. Begin
  547. case c of
  548. 'O' :
  549. Begin
  550. actasmpattern:=tostr(ValOctal(actasmpattern));
  551. actasmtoken:=AS_INTNUM;
  552. c:=current_scanner.asmgetchar;
  553. exit;
  554. end;
  555. 'H' :
  556. Begin
  557. actasmpattern:=tostr(ValHexaDecimal(actasmpattern));
  558. actasmtoken:=AS_INTNUM;
  559. c:=current_scanner.asmgetchar;
  560. exit;
  561. end;
  562. else { must be an integer number }
  563. begin
  564. actasmpattern:=tostr(ValDecimal(actasmpattern));
  565. actasmtoken:=AS_INTNUM;
  566. exit;
  567. end;
  568. end;
  569. end;
  570. end;
  571. ';','{',#13,newline :
  572. begin
  573. c:=current_scanner.asmgetchar;
  574. firsttoken:=TRUE;
  575. actasmtoken:=AS_SEPARATOR;
  576. exit;
  577. end;
  578. else
  579. current_scanner.illegal_char(c);
  580. end;
  581. end;
  582. end;
  583. function consume(t : tasmtoken):boolean;
  584. begin
  585. Consume:=true;
  586. if t<>actasmtoken then
  587. begin
  588. Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
  589. Consume:=false;
  590. end;
  591. repeat
  592. gettoken;
  593. until actasmtoken<>AS_NONE;
  594. end;
  595. procedure RecoverConsume(allowcomma:boolean);
  596. begin
  597. While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
  598. begin
  599. if allowcomma and (actasmtoken=AS_COMMA) then
  600. break;
  601. Consume(actasmtoken);
  602. end;
  603. end;
  604. {*****************************************************************************
  605. Parsing Helpers
  606. *****************************************************************************}
  607. Procedure BuildRecordOffsetSize(const expr: string;var offset:longint;var size:longint);
  608. { Description: This routine builds up a record offset after a AS_DOT }
  609. { token is encountered. }
  610. { On entry actasmtoken should be equal to AS_DOT }
  611. var
  612. s : string;
  613. Begin
  614. offset:=0;
  615. size:=0;
  616. s:=expr;
  617. while (actasmtoken=AS_DOT) do
  618. begin
  619. Consume(AS_DOT);
  620. if actasmtoken=AS_ID then
  621. s:=s+'.'+actasmpattern;
  622. if not Consume(AS_ID) then
  623. begin
  624. RecoverConsume(true);
  625. break;
  626. end;
  627. end;
  628. if not GetRecordOffsetSize(s,offset,size) then
  629. Message(asmr_e_building_record_offset);
  630. end;
  631. Procedure BuildConstSymbolExpression(needofs,exitreg:boolean;var value:longint;var asmsym:string);
  632. var
  633. tempstr,expr,hs : string;
  634. parenlevel,l,k : longint;
  635. errorflag : boolean;
  636. prevtok : tasmtoken;
  637. hl : tasmlabel;
  638. sym : tsym;
  639. srsymtable : tsymtable;
  640. Begin
  641. { reset }
  642. value:=0;
  643. asmsym:='';
  644. errorflag:=FALSE;
  645. tempstr:='';
  646. expr:='';
  647. inexpression:=TRUE;
  648. parenlevel:=0;
  649. Repeat
  650. Case actasmtoken of
  651. AS_LPAREN:
  652. Begin
  653. Consume(AS_LPAREN);
  654. expr:=expr + '(';
  655. inc(parenlevel);
  656. end;
  657. AS_RPAREN:
  658. Begin
  659. Consume(AS_RPAREN);
  660. expr:=expr + ')';
  661. dec(parenlevel);
  662. end;
  663. AS_SHL:
  664. Begin
  665. Consume(AS_SHL);
  666. expr:=expr + '<';
  667. end;
  668. AS_SHR:
  669. Begin
  670. Consume(AS_SHR);
  671. expr:=expr + '>';
  672. end;
  673. AS_SLASH:
  674. Begin
  675. Consume(AS_SLASH);
  676. expr:=expr + '/';
  677. end;
  678. AS_MOD:
  679. Begin
  680. Consume(AS_MOD);
  681. expr:=expr + '%';
  682. end;
  683. AS_STAR:
  684. Begin
  685. Consume(AS_STAR);
  686. if exitreg and (actasmtoken=AS_REGISTER) then
  687. break;
  688. expr:=expr + '*';
  689. end;
  690. AS_PLUS:
  691. Begin
  692. Consume(AS_PLUS);
  693. if exitreg and (actasmtoken=AS_REGISTER) then
  694. break;
  695. expr:=expr + '+';
  696. end;
  697. AS_MINUS:
  698. Begin
  699. Consume(AS_MINUS);
  700. expr:=expr + '-';
  701. end;
  702. AS_AND:
  703. Begin
  704. Consume(AS_AND);
  705. expr:=expr + '&';
  706. end;
  707. AS_NOT:
  708. Begin
  709. Consume(AS_NOT);
  710. expr:=expr + '~';
  711. end;
  712. AS_XOR:
  713. Begin
  714. Consume(AS_XOR);
  715. expr:=expr + '^';
  716. end;
  717. AS_OR:
  718. Begin
  719. Consume(AS_OR);
  720. expr:=expr + '|';
  721. end;
  722. AS_INTNUM:
  723. Begin
  724. expr:=expr + actasmpattern;
  725. Consume(AS_INTNUM);
  726. end;
  727. AS_OFFSET:
  728. begin
  729. Consume(AS_OFFSET);
  730. if actasmtoken<>AS_ID then
  731. Message(asmr_e_offset_without_identifier);
  732. end;
  733. AS_TYPE:
  734. begin
  735. l:=0;
  736. Consume(AS_TYPE);
  737. if actasmtoken<>AS_ID then
  738. Message(asmr_e_type_without_identifier)
  739. else
  740. begin
  741. tempstr:=actasmpattern;
  742. Consume(AS_ID);
  743. if actasmtoken=AS_DOT then
  744. BuildRecordOffsetSize(tempstr,k,l)
  745. else
  746. begin
  747. searchsym(tempstr,sym,srsymtable);
  748. if assigned(sym) then
  749. begin
  750. case sym.typ of
  751. varsym :
  752. l:=tvarsym(sym).getsize;
  753. typedconstsym :
  754. l:=ttypedconstsym(sym).getsize;
  755. typesym :
  756. l:=ttypesym(sym).restype.def.size;
  757. else
  758. Message(asmr_e_wrong_sym_type);
  759. end;
  760. end
  761. else
  762. Message1(sym_e_unknown_id,tempstr);
  763. end;
  764. end;
  765. str(l, tempstr);
  766. expr:=expr + tempstr;
  767. end;
  768. AS_STRING:
  769. Begin
  770. l:=0;
  771. case Length(actasmpattern) of
  772. 1 :
  773. l:=ord(actasmpattern[1]);
  774. 2 :
  775. l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
  776. 3 :
  777. l:=ord(actasmpattern[3]) +
  778. Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
  779. 4 :
  780. l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
  781. Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
  782. else
  783. Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
  784. end;
  785. str(l, tempstr);
  786. expr:=expr + tempstr;
  787. Consume(AS_STRING);
  788. end;
  789. AS_ID:
  790. Begin
  791. hs:='';
  792. tempstr:=actasmpattern;
  793. prevtok:=prevasmtoken;
  794. consume(AS_ID);
  795. if SearchIConstant(tempstr,l) then
  796. begin
  797. str(l, tempstr);
  798. expr:=expr + tempstr;
  799. end
  800. else
  801. begin
  802. if is_locallabel(tempstr) then
  803. begin
  804. CreateLocalLabel(tempstr,hl,false);
  805. hs:=hl.name
  806. end
  807. else
  808. if SearchLabel(tempstr,hl,false) then
  809. hs:=hl.name
  810. else
  811. begin
  812. searchsym(tempstr,sym,srsymtable);
  813. if assigned(sym) then
  814. begin
  815. case sym.typ of
  816. varsym :
  817. begin
  818. if sym.owner.symtabletype in [localsymtable,parasymtable] then
  819. Message(asmr_e_no_local_or_para_allowed);
  820. hs:=tvarsym(sym).mangledname;
  821. end;
  822. typedconstsym :
  823. hs:=ttypedconstsym(sym).mangledname;
  824. procsym :
  825. begin
  826. if Tprocsym(sym).procdef_count>1 then
  827. Message(asmr_w_calling_overload_func);
  828. hs:=tprocsym(sym).first_procdef.mangledname;
  829. end;
  830. typesym :
  831. begin
  832. if not(ttypesym(sym).restype.def.deftype in [recorddef,objectdef]) then
  833. Message(asmr_e_wrong_sym_type);
  834. end;
  835. else
  836. Message(asmr_e_wrong_sym_type);
  837. end;
  838. end
  839. else
  840. Message1(sym_e_unknown_id,tempstr);
  841. end;
  842. { symbol found? }
  843. if hs<>'' then
  844. begin
  845. if needofs and (prevtok<>AS_OFFSET) then
  846. Message(asmr_e_need_offset);
  847. if asmsym='' then
  848. asmsym:=hs
  849. else
  850. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  851. if (expr='') or (expr[length(expr)]='+') then
  852. begin
  853. { don't remove the + if there could be a record field }
  854. if actasmtoken<>AS_DOT then
  855. delete(expr,length(expr),1);
  856. end
  857. else
  858. Message(asmr_e_only_add_relocatable_symbol);
  859. end;
  860. if actasmtoken=AS_DOT then
  861. begin
  862. BuildRecordOffsetSize(tempstr,l,k);
  863. str(l, tempstr);
  864. expr:=expr + tempstr;
  865. end
  866. else
  867. begin
  868. if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
  869. delete(expr,length(expr),1);
  870. end;
  871. end;
  872. { check if there are wrong operator used like / or mod etc. }
  873. if (hs<>'') and not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,AS_END,AS_RBRACKET]) then
  874. Message(asmr_e_only_add_relocatable_symbol);
  875. end;
  876. AS_END,
  877. AS_RBRACKET,
  878. AS_SEPARATOR,
  879. AS_COMMA:
  880. Begin
  881. break;
  882. end;
  883. else
  884. Begin
  885. { write error only once. }
  886. if not errorflag then
  887. Message(asmr_e_invalid_constant_expression);
  888. { consume tokens until we find COMMA or SEPARATOR }
  889. Consume(actasmtoken);
  890. errorflag:=TRUE;
  891. end;
  892. end;
  893. Until false;
  894. { calculate expression }
  895. if not ErrorFlag then
  896. value:=CalculateExpression(expr)
  897. else
  898. value:=0;
  899. { no longer in an expression }
  900. inexpression:=FALSE;
  901. end;
  902. Function BuildConstExpression:longint;
  903. var
  904. l : longint;
  905. hs : string;
  906. begin
  907. BuildConstSymbolExpression(false,false,l,hs);
  908. if hs<>'' then
  909. Message(asmr_e_relocatable_symbol_not_allowed);
  910. BuildConstExpression:=l;
  911. end;
  912. Function BuildRefConstExpression:longint;
  913. var
  914. l : longint;
  915. hs : string;
  916. begin
  917. BuildConstSymbolExpression(false,true,l,hs);
  918. if hs<>'' then
  919. Message(asmr_e_relocatable_symbol_not_allowed);
  920. BuildRefConstExpression:=l;
  921. end;
  922. {****************************************************************************
  923. T386IntelOperand
  924. ****************************************************************************}
  925. type
  926. T386IntelOperand=class(T386Operand)
  927. Procedure BuildOperand;override;
  928. private
  929. Procedure BuildReference;
  930. Procedure BuildConstant;
  931. end;
  932. Procedure T386IntelOperand.BuildReference;
  933. var
  934. k,l,scale : longint;
  935. tempstr2,
  936. tempstr,hs : string;
  937. code : integer;
  938. hreg,
  939. oldbase : tregister;
  940. GotStar,GotOffset,HadVar,
  941. GotPlus,Negative : boolean;
  942. Begin
  943. Consume(AS_LBRACKET);
  944. InitRef;
  945. GotStar:=false;
  946. GotPlus:=true;
  947. GotOffset:=false;
  948. Negative:=false;
  949. Scale:=0;
  950. repeat
  951. if GotOffset and (actasmtoken<>AS_ID) then
  952. Message(asmr_e_invalid_reference_syntax);
  953. Case actasmtoken of
  954. AS_ID: { Constant reference expression OR variable reference expression }
  955. Begin
  956. if not GotPlus then
  957. Message(asmr_e_invalid_reference_syntax);
  958. if actasmpattern[1] = '@' then
  959. Message(asmr_e_local_label_not_allowed_as_ref);
  960. GotStar:=false;
  961. GotPlus:=false;
  962. if SearchIConstant(actasmpattern,l) or
  963. SearchRecordType(actasmpattern) then
  964. begin
  965. l:=BuildRefConstExpression;
  966. GotPlus:=(prevasmtoken=AS_PLUS);
  967. GotStar:=(prevasmtoken=AS_STAR);
  968. if GotStar then
  969. opr.ref.scalefactor:=l
  970. else
  971. begin
  972. if negative then
  973. Dec(opr.ref.offset,l)
  974. else
  975. Inc(opr.ref.offset,l);
  976. end;
  977. end
  978. else
  979. Begin
  980. if hasvar and not GotOffset then
  981. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  982. HadVar:=hasvar and GotOffset;
  983. if negative then
  984. Message(asmr_e_only_add_relocatable_symbol);
  985. oldbase:=opr.ref.base;
  986. opr.ref.base:=NR_NO;
  987. tempstr:=actasmpattern;
  988. Consume(AS_ID);
  989. { typecasting? }
  990. if (actasmtoken=AS_LPAREN) and
  991. SearchType(tempstr) then
  992. begin
  993. hastype:=true;
  994. Consume(AS_LPAREN);
  995. tempstr2:=actasmpattern;
  996. Consume(AS_ID);
  997. Consume(AS_RPAREN);
  998. if not SetupVar(tempstr2,GotOffset) then
  999. Message1(sym_e_unknown_id,tempstr2);
  1000. end
  1001. else
  1002. if not SetupVar(tempstr,GotOffset) then
  1003. Message1(sym_e_unknown_id,tempstr);
  1004. { record.field ? }
  1005. if actasmtoken=AS_DOT then
  1006. begin
  1007. BuildRecordOffsetSize(tempstr,l,k);
  1008. inc(opr.ref.offset,l);
  1009. end;
  1010. if GotOffset then
  1011. begin
  1012. if hasvar and (opr.ref.base=current_procinfo.framepointer) then
  1013. begin
  1014. opr.ref.base:=NR_NO;
  1015. hasvar:=hadvar;
  1016. end
  1017. else
  1018. begin
  1019. if hasvar and hadvar then
  1020. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1021. { should we allow ?? }
  1022. end;
  1023. end;
  1024. { is the base register loaded by the var ? }
  1025. if (opr.ref.base<>NR_NO) then
  1026. begin
  1027. { check if we can move the old base to the index register }
  1028. if (opr.ref.index<>NR_NO) then
  1029. Message(asmr_e_wrong_base_index)
  1030. else
  1031. opr.ref.index:=oldbase;
  1032. end
  1033. else
  1034. opr.ref.base:=oldbase;
  1035. { we can't have a Constant here so add the constant value to the
  1036. offset }
  1037. if opr.typ=OPR_CONSTANT then
  1038. begin
  1039. opr.typ:=OPR_REFERENCE;
  1040. inc(opr.ref.offset,opr.val);
  1041. end;
  1042. end;
  1043. GotOffset:=false;
  1044. end;
  1045. AS_PLUS :
  1046. Begin
  1047. Consume(AS_PLUS);
  1048. Negative:=false;
  1049. GotPlus:=true;
  1050. GotStar:=false;
  1051. Scale:=0;
  1052. end;
  1053. AS_MINUS :
  1054. begin
  1055. Consume(AS_MINUS);
  1056. Negative:=true;
  1057. GotPlus:=true;
  1058. GotStar:=false;
  1059. Scale:=0;
  1060. end;
  1061. AS_STAR : { Scaling, with eax*4 order }
  1062. begin
  1063. Consume(AS_STAR);
  1064. hs:='';
  1065. l:=0;
  1066. case actasmtoken of
  1067. AS_LPAREN :
  1068. l:=BuildConstExpression;
  1069. AS_INTNUM:
  1070. Begin
  1071. hs:=actasmpattern;
  1072. Consume(AS_INTNUM);
  1073. end;
  1074. AS_REGISTER :
  1075. begin
  1076. if opr.ref.scalefactor=0 then
  1077. if scale<>0 then
  1078. begin
  1079. opr.ref.scalefactor:=scale;
  1080. scale:=0;
  1081. end
  1082. else
  1083. Message(asmr_e_wrong_scale_factor);
  1084. end;
  1085. else
  1086. Message(asmr_e_invalid_reference_syntax);
  1087. end;
  1088. if actasmtoken<>AS_REGISTER then
  1089. begin
  1090. if hs<>'' then
  1091. val(hs,l,code);
  1092. opr.ref.scalefactor:=l;
  1093. if l>9 then
  1094. Message(asmr_e_wrong_scale_factor);
  1095. end;
  1096. GotPlus:=false;
  1097. GotStar:=false;
  1098. end;
  1099. AS_REGISTER :
  1100. begin
  1101. if not((GotPlus and (not Negative)) or
  1102. GotStar) then
  1103. Message(asmr_e_invalid_reference_syntax);
  1104. hreg:=actasmregister;
  1105. Consume(AS_REGISTER);
  1106. { this register will be the index:
  1107. 1. just read a *
  1108. 2. next token is a *
  1109. 3. base register is already used }
  1110. if (GotStar) or
  1111. (actasmtoken=AS_STAR) or
  1112. (opr.ref.base<>NR_NO) then
  1113. begin
  1114. if (opr.ref.index<>NR_NO) then
  1115. Message(asmr_e_multiple_index);
  1116. opr.ref.index:=hreg;
  1117. if scale<>0 then
  1118. begin
  1119. opr.ref.scalefactor:=scale;
  1120. scale:=0;
  1121. end;
  1122. end
  1123. else
  1124. opr.ref.base:=hreg;
  1125. GotPlus:=false;
  1126. GotStar:=false;
  1127. end;
  1128. AS_OFFSET :
  1129. begin
  1130. Consume(AS_OFFSET);
  1131. GotOffset:=true;
  1132. end;
  1133. AS_TYPE,
  1134. AS_NOT,
  1135. AS_STRING,
  1136. AS_INTNUM,
  1137. AS_LPAREN : { Constant reference expression }
  1138. begin
  1139. if not GotPlus and not GotStar then
  1140. Message(asmr_e_invalid_reference_syntax);
  1141. BuildConstSymbolExpression(true,true,l,tempstr);
  1142. if tempstr<>'' then
  1143. begin
  1144. if GotStar then
  1145. Message(asmr_e_only_add_relocatable_symbol);
  1146. if not assigned(opr.ref.symbol) then
  1147. opr.ref.symbol:=objectlibrary.newasmsymbol(tempstr)
  1148. else
  1149. Message(asmr_e_cant_have_multiple_relocatable_symbols);
  1150. end;
  1151. if GotStar then
  1152. opr.ref.scalefactor:=l
  1153. else if (prevasmtoken = AS_STAR) then
  1154. begin
  1155. if scale<>0 then
  1156. scale:=l*scale
  1157. else
  1158. scale:=l;
  1159. end
  1160. else
  1161. begin
  1162. if negative then
  1163. Dec(opr.ref.offset,l)
  1164. else
  1165. Inc(opr.ref.offset,l);
  1166. end;
  1167. GotPlus:=(prevasmtoken=AS_PLUS) or
  1168. (prevasmtoken=AS_MINUS);
  1169. if GotPlus then
  1170. negative := prevasmtoken = AS_MINUS;
  1171. GotStar:=(prevasmtoken=AS_STAR);
  1172. end;
  1173. AS_RBRACKET :
  1174. begin
  1175. if GotPlus or GotStar then
  1176. Message(asmr_e_invalid_reference_syntax);
  1177. Consume(AS_RBRACKET);
  1178. break;
  1179. end;
  1180. else
  1181. Begin
  1182. Message(asmr_e_invalid_reference_syntax);
  1183. RecoverConsume(true);
  1184. break;
  1185. end;
  1186. end;
  1187. until false;
  1188. end;
  1189. Procedure T386IntelOperand.BuildConstant;
  1190. var
  1191. l : longint;
  1192. tempstr : string;
  1193. begin
  1194. BuildConstSymbolExpression(true,false,l,tempstr);
  1195. if tempstr<>'' then
  1196. begin
  1197. opr.typ:=OPR_SYMBOL;
  1198. opr.symofs:=l;
  1199. opr.symbol:=objectlibrary.newasmsymbol(tempstr);
  1200. end
  1201. else
  1202. begin
  1203. opr.typ:=OPR_CONSTANT;
  1204. opr.val:=l;
  1205. end;
  1206. end;
  1207. Procedure T386IntelOperand.BuildOperand;
  1208. var
  1209. tempstr,
  1210. expr : string;
  1211. tempreg : tregister;
  1212. l : longint;
  1213. hl : tasmlabel;
  1214. procedure AddLabelOperand(hl:tasmlabel);
  1215. begin
  1216. if is_calljmp(actopcode) then
  1217. begin
  1218. opr.typ:=OPR_SYMBOL;
  1219. opr.symbol:=hl;
  1220. end
  1221. else
  1222. begin
  1223. InitRef;
  1224. opr.ref.symbol:=hl;
  1225. end;
  1226. end;
  1227. procedure MaybeRecordOffset;
  1228. var
  1229. l,
  1230. toffset,
  1231. tsize : longint;
  1232. begin
  1233. if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
  1234. exit;
  1235. l:=0;
  1236. if actasmtoken=AS_DOT then
  1237. begin
  1238. { if no type was specified before the [] then we expect the
  1239. first ID to be the type }
  1240. if expr='' then
  1241. begin
  1242. consume(AS_DOT);
  1243. if actasmtoken=AS_ID then
  1244. begin
  1245. expr:=actasmpattern;
  1246. consume(AS_ID);
  1247. { now the next one must the be the dot }
  1248. if actasmtoken<>AS_DOT then
  1249. begin
  1250. { if it is not a dot then we expect a constant
  1251. value as offset }
  1252. if not SearchIConstant(expr,l) then
  1253. Message(asmr_e_building_record_offset);
  1254. expr:='';
  1255. end;
  1256. end
  1257. else
  1258. Message(asmr_e_no_var_type_specified)
  1259. end;
  1260. if expr<>'' then
  1261. begin
  1262. BuildRecordOffsetSize(expr,toffset,tsize);
  1263. inc(l,toffset);
  1264. SetSize(tsize,true);
  1265. end;
  1266. end;
  1267. if actasmtoken in [AS_PLUS,AS_MINUS] then
  1268. inc(l,BuildConstExpression);
  1269. case opr.typ of
  1270. OPR_LOCAL :
  1271. begin
  1272. { don't allow direct access to fields of parameters, becuase that
  1273. will generate buggy code. Allow it only for explicit typecasting
  1274. and when the parameter is in a register (delphi compatible) }
  1275. if (not hastype) and
  1276. (tvarsym(opr.localsym).owner.symtabletype=parasymtable) and
  1277. (current_procinfo.procdef.proccalloption<>pocall_register) then
  1278. Message(asmr_e_cannot_access_field_directly_for_parameters);
  1279. inc(opr.localsymofs,l)
  1280. end;
  1281. OPR_CONSTANT :
  1282. inc(opr.val,l);
  1283. OPR_REFERENCE :
  1284. inc(opr.ref.offset,l);
  1285. else
  1286. internalerror(200309222);
  1287. end;
  1288. end;
  1289. Begin
  1290. expr:='';
  1291. case actasmtoken of
  1292. AS_OFFSET,
  1293. AS_TYPE,
  1294. AS_INTNUM,
  1295. AS_PLUS,
  1296. AS_MINUS,
  1297. AS_NOT,
  1298. AS_LPAREN,
  1299. AS_STRING :
  1300. Begin
  1301. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1302. Message(asmr_e_invalid_operand_type);
  1303. BuildConstant;
  1304. end;
  1305. AS_ID : { A constant expression, or a Variable ref. }
  1306. Begin
  1307. { Label or Special symbol reference? }
  1308. if actasmpattern[1] = '@' then
  1309. Begin
  1310. if actasmpattern = '@RESULT' then
  1311. Begin
  1312. InitRef;
  1313. SetupResult;
  1314. Consume(AS_ID);
  1315. end
  1316. else
  1317. if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1318. begin
  1319. Message(asmr_w_CODE_and_DATA_not_supported);
  1320. Consume(AS_ID);
  1321. end
  1322. else
  1323. { Local Label }
  1324. begin
  1325. CreateLocalLabel(actasmpattern,hl,false);
  1326. Consume(AS_ID);
  1327. AddLabelOperand(hl);
  1328. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1329. Message(asmr_e_syntax_error);
  1330. end;
  1331. end
  1332. else
  1333. { support result for delphi modes }
  1334. if (m_objpas in aktmodeswitches) and (actasmpattern='RESULT') then
  1335. begin
  1336. InitRef;
  1337. SetUpResult;
  1338. Consume(AS_ID);
  1339. end
  1340. { probably a variable or normal expression }
  1341. { or a procedure (such as in CALL ID) }
  1342. else
  1343. Begin
  1344. { is it a constant ? }
  1345. if SearchIConstant(actasmpattern,l) then
  1346. Begin
  1347. if not (opr.typ in [OPR_NONE,OPR_CONSTANT]) then
  1348. Message(asmr_e_invalid_operand_type);
  1349. BuildConstant;
  1350. end
  1351. else
  1352. { Check for pascal label }
  1353. if SearchLabel(actasmpattern,hl,false) then
  1354. begin
  1355. Consume(AS_ID);
  1356. AddLabelOperand(hl);
  1357. if not (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1358. Message(asmr_e_syntax_error);
  1359. end
  1360. else
  1361. { is it a normal variable ? }
  1362. Begin
  1363. InitRef;
  1364. expr:=actasmpattern;
  1365. Consume(AS_ID);
  1366. { typecasting? }
  1367. if (actasmtoken=AS_LPAREN) and
  1368. SearchType(expr) then
  1369. begin
  1370. hastype:=true;
  1371. Consume(AS_LPAREN);
  1372. tempstr:=actasmpattern;
  1373. Consume(AS_ID);
  1374. Consume(AS_RPAREN);
  1375. if SetupVar(tempstr,false) then
  1376. begin
  1377. MaybeRecordOffset;
  1378. { add a constant expression? }
  1379. if (actasmtoken=AS_PLUS) then
  1380. begin
  1381. l:=BuildConstExpression;
  1382. if opr.typ=OPR_CONSTANT then
  1383. inc(opr.val,l)
  1384. else
  1385. inc(opr.ref.offset,l);
  1386. end
  1387. end
  1388. else
  1389. Message1(sym_e_unknown_id,tempstr);
  1390. end
  1391. else
  1392. begin
  1393. if SetupVar(expr,false) then
  1394. begin
  1395. MaybeRecordOffset;
  1396. { add a constant expression? }
  1397. if (actasmtoken=AS_PLUS) then
  1398. begin
  1399. l:=BuildConstExpression;
  1400. case opr.typ of
  1401. OPR_CONSTANT :
  1402. inc(opr.val,l);
  1403. OPR_LOCAL :
  1404. inc(opr.localsymofs,l);
  1405. OPR_REFERENCE :
  1406. inc(opr.ref.offset,l);
  1407. else
  1408. internalerror(200309203);
  1409. end;
  1410. end
  1411. end
  1412. else
  1413. Begin
  1414. { not a variable, check special variables.. }
  1415. if expr = 'SELF' then
  1416. SetupSelf
  1417. else
  1418. Message1(sym_e_unknown_id,expr);
  1419. end;
  1420. end;
  1421. end;
  1422. { handle references }
  1423. if actasmtoken=AS_LBRACKET then
  1424. begin
  1425. if opr.typ=OPR_CONSTANT then
  1426. begin
  1427. l:=opr.val;
  1428. opr.typ:=OPR_REFERENCE;
  1429. reference_reset(opr.ref);
  1430. opr.Ref.Offset:=l;
  1431. end;
  1432. BuildReference;
  1433. MaybeRecordOffset;
  1434. end;
  1435. end;
  1436. end;
  1437. AS_REGISTER : { Register, a variable reference or a constant reference }
  1438. begin
  1439. { save the type of register used. }
  1440. tempreg:=actasmregister;
  1441. Consume(AS_REGISTER);
  1442. if actasmtoken = AS_COLON then
  1443. Begin
  1444. Consume(AS_COLON);
  1445. InitRef;
  1446. opr.ref.segment:=tempreg;
  1447. BuildReference;
  1448. end
  1449. else
  1450. { Simple register }
  1451. begin
  1452. if not (opr.typ in [OPR_NONE,OPR_REGISTER]) then
  1453. Message(asmr_e_invalid_operand_type);
  1454. opr.typ:=OPR_REGISTER;
  1455. opr.reg:=tempreg;
  1456. SetSize(tcgsize2size[cg.reg_cgsize(opr.reg)],true);
  1457. end;
  1458. end;
  1459. AS_LBRACKET: { a variable reference, register ref. or a constant reference }
  1460. Begin
  1461. InitRef;
  1462. BuildReference;
  1463. MaybeRecordOffset;
  1464. end;
  1465. AS_SEG :
  1466. Begin
  1467. Message(asmr_e_seg_not_supported);
  1468. Consume(actasmtoken);
  1469. end;
  1470. AS_SEPARATOR,
  1471. AS_END,
  1472. AS_COMMA: ;
  1473. else
  1474. Message(asmr_e_syn_operand);
  1475. end;
  1476. if not(actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
  1477. begin
  1478. Message(asmr_e_syntax_error);
  1479. RecoverConsume(true);
  1480. end;
  1481. end;
  1482. {*****************************************************************************
  1483. T386IntelInstruction
  1484. *****************************************************************************}
  1485. type
  1486. T386IntelInstruction=class(T386Instruction)
  1487. procedure InitOperands;override;
  1488. procedure BuildOpcode;override;
  1489. end;
  1490. procedure T386IntelInstruction.InitOperands;
  1491. var
  1492. i : longint;
  1493. begin
  1494. for i:=1 to 3 do
  1495. Operands[i]:=T386IntelOperand.Create;
  1496. end;
  1497. Procedure T386IntelInstruction.BuildOpCode;
  1498. var
  1499. PrefixOp,OverrideOp: tasmop;
  1500. size,
  1501. operandnum : longint;
  1502. Begin
  1503. PrefixOp:=A_None;
  1504. OverrideOp:=A_None;
  1505. { prefix seg opcode / prefix opcode }
  1506. repeat
  1507. if is_prefix(actopcode) then
  1508. begin
  1509. OpOrder:=op_intel;
  1510. PrefixOp:=ActOpcode;
  1511. opcode:=ActOpcode;
  1512. condition:=ActCondition;
  1513. opsize:=ActOpsize;
  1514. ConcatInstruction(curlist);
  1515. Consume(AS_OPCODE);
  1516. end
  1517. else
  1518. if is_override(actopcode) then
  1519. begin
  1520. OpOrder:=op_intel;
  1521. OverrideOp:=ActOpcode;
  1522. opcode:=ActOpcode;
  1523. condition:=ActCondition;
  1524. opsize:=ActOpsize;
  1525. ConcatInstruction(curlist);
  1526. Consume(AS_OPCODE);
  1527. end
  1528. else
  1529. break;
  1530. { allow for newline after prefix or override }
  1531. while actasmtoken=AS_SEPARATOR do
  1532. Consume(AS_SEPARATOR);
  1533. until (actasmtoken<>AS_OPCODE);
  1534. { opcode }
  1535. if (actasmtoken <> AS_OPCODE) then
  1536. Begin
  1537. Message(asmr_e_invalid_or_missing_opcode);
  1538. RecoverConsume(false);
  1539. exit;
  1540. end;
  1541. { Fill the instr object with the current state }
  1542. OpOrder:=op_intel;
  1543. Opcode:=ActOpcode;
  1544. condition:=ActCondition;
  1545. opsize:=ActOpsize;
  1546. { Valid combination of prefix/override and instruction ? }
  1547. if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
  1548. Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
  1549. if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
  1550. Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
  1551. { We are reading operands, so opcode will be an AS_ID }
  1552. operandnum:=1;
  1553. Consume(AS_OPCODE);
  1554. { Zero operand opcode ? }
  1555. if actasmtoken in [AS_SEPARATOR,AS_END] then
  1556. begin
  1557. operandnum:=0;
  1558. exit;
  1559. end;
  1560. { Read Operands }
  1561. repeat
  1562. case actasmtoken of
  1563. { End of asm operands for this opcode }
  1564. AS_END,
  1565. AS_SEPARATOR :
  1566. break;
  1567. { Operand delimiter }
  1568. AS_COMMA :
  1569. Begin
  1570. if operandnum > Max_Operands then
  1571. Message(asmr_e_too_many_operands)
  1572. else
  1573. Inc(operandnum);
  1574. Consume(AS_COMMA);
  1575. end;
  1576. { Typecast, Constant Expression, Type Specifier }
  1577. AS_DWORD,
  1578. AS_BYTE,
  1579. AS_WORD,
  1580. AS_TBYTE,
  1581. AS_QWORD :
  1582. Begin
  1583. { load the size in a temp variable, so it can be set when the
  1584. operand is read }
  1585. size:=0;
  1586. Case actasmtoken of
  1587. AS_DWORD : size:=4;
  1588. AS_WORD : size:=2;
  1589. AS_BYTE : size:=1;
  1590. AS_QWORD : size:=8;
  1591. AS_TBYTE : size:=extended_size;
  1592. end;
  1593. Consume(actasmtoken);
  1594. if actasmtoken=AS_PTR then
  1595. begin
  1596. Consume(AS_PTR);
  1597. Operands[operandnum].InitRef;
  1598. end;
  1599. Operands[operandnum].BuildOperand;
  1600. { now set the size which was specified by the override }
  1601. Operands[operandnum].setsize(size,true);
  1602. end;
  1603. { Type specifier }
  1604. AS_NEAR,
  1605. AS_FAR :
  1606. Begin
  1607. if actasmtoken = AS_NEAR then
  1608. begin
  1609. Message(asmr_w_near_ignored);
  1610. opsize:=S_NEAR;
  1611. end
  1612. else
  1613. begin
  1614. Message(asmr_w_far_ignored);
  1615. opsize:=S_FAR;
  1616. end;
  1617. Consume(actasmtoken);
  1618. if actasmtoken=AS_PTR then
  1619. begin
  1620. Consume(AS_PTR);
  1621. Operands[operandnum].InitRef;
  1622. end;
  1623. Operands[operandnum].BuildOperand;
  1624. end;
  1625. else
  1626. Operands[operandnum].BuildOperand;
  1627. end; { end case }
  1628. until false;
  1629. Ops:=operandnum;
  1630. end;
  1631. Procedure BuildConstant(maxvalue: longint);
  1632. var
  1633. strlength: byte;
  1634. asmsym,
  1635. expr: string;
  1636. value : longint;
  1637. Begin
  1638. strlength:=0; { assume it is a DB }
  1639. Repeat
  1640. Case actasmtoken of
  1641. AS_STRING:
  1642. Begin
  1643. if maxvalue = $ffff then
  1644. strlength:=2
  1645. else
  1646. if maxvalue = longint($ffffffff) then
  1647. strlength:=4;
  1648. { DD and DW cases }
  1649. if strlength <> 0 then
  1650. Begin
  1651. if Not PadZero(actasmpattern,strlength) then
  1652. Message(scan_f_string_exceeds_line);
  1653. end;
  1654. expr:=actasmpattern;
  1655. Consume(AS_STRING);
  1656. Case actasmtoken of
  1657. AS_COMMA:
  1658. Consume(AS_COMMA);
  1659. AS_END,
  1660. AS_SEPARATOR: ;
  1661. else
  1662. Message(asmr_e_invalid_string_expression);
  1663. end;
  1664. ConcatString(curlist,expr);
  1665. end;
  1666. AS_PLUS,
  1667. AS_MINUS,
  1668. AS_LPAREN,
  1669. AS_NOT,
  1670. AS_INTNUM,
  1671. AS_ID :
  1672. Begin
  1673. BuildConstSymbolExpression(false,false,value,asmsym);
  1674. if asmsym<>'' then
  1675. begin
  1676. if maxvalue<>longint($ffffffff) then
  1677. Message1(asmr_w_const32bit_for_address,asmsym);
  1678. ConcatConstSymbol(curlist,asmsym,value)
  1679. end
  1680. else
  1681. ConcatConstant(curlist,value,maxvalue);
  1682. end;
  1683. AS_COMMA:
  1684. Consume(AS_COMMA);
  1685. AS_END,
  1686. AS_SEPARATOR:
  1687. break;
  1688. else
  1689. begin
  1690. Message(asmr_e_syn_constant);
  1691. RecoverConsume(false);
  1692. end
  1693. end;
  1694. Until false;
  1695. end;
  1696. Function Assemble: tnode;
  1697. Var
  1698. hl : tasmlabel;
  1699. instr : T386IntelInstruction;
  1700. Begin
  1701. Message1(asmr_d_start_reading,'intel');
  1702. inexpression:=FALSE;
  1703. firsttoken:=TRUE;
  1704. { sets up all opcode and register tables in uppercase }
  1705. if not _asmsorted then
  1706. Begin
  1707. SetupTables;
  1708. _asmsorted:=TRUE;
  1709. end;
  1710. curlist:=TAAsmoutput.Create;
  1711. { setup label linked list }
  1712. LocalLabelList:=TLocalLabelList.Create;
  1713. { start tokenizer }
  1714. c:=current_scanner.asmgetchar;
  1715. gettoken;
  1716. { main loop }
  1717. repeat
  1718. case actasmtoken of
  1719. AS_LLABEL:
  1720. Begin
  1721. if CreateLocalLabel(actasmpattern,hl,true) then
  1722. ConcatLabel(curlist,hl);
  1723. Consume(AS_LLABEL);
  1724. end;
  1725. AS_LABEL:
  1726. Begin
  1727. if SearchLabel(upper(actasmpattern),hl,true) then
  1728. ConcatLabel(curlist,hl)
  1729. else
  1730. Message1(asmr_e_unknown_label_identifier,actasmpattern);
  1731. Consume(AS_LABEL);
  1732. end;
  1733. AS_DW :
  1734. Begin
  1735. inexpression:=true;
  1736. Consume(AS_DW);
  1737. BuildConstant($ffff);
  1738. inexpression:=false;
  1739. end;
  1740. AS_DB :
  1741. Begin
  1742. inexpression:=true;
  1743. Consume(AS_DB);
  1744. BuildConstant($ff);
  1745. inexpression:=false;
  1746. end;
  1747. AS_DD :
  1748. Begin
  1749. inexpression:=true;
  1750. Consume(AS_DD);
  1751. BuildConstant(longint($ffffffff));
  1752. inexpression:=false;
  1753. end;
  1754. AS_OPCODE :
  1755. Begin
  1756. instr:=T386IntelInstruction.Create;
  1757. instr.BuildOpcode;
  1758. { We need AT&T style operands }
  1759. instr.Swapoperands;
  1760. { Must be done with args in ATT order }
  1761. instr.CheckNonCommutativeOpcodes;
  1762. instr.AddReferenceSizes;
  1763. instr.SetInstructionOpsize;
  1764. instr.CheckOperandSizes;
  1765. instr.ConcatInstruction(curlist);
  1766. instr.Free;
  1767. end;
  1768. AS_SEPARATOR :
  1769. Begin
  1770. Consume(AS_SEPARATOR);
  1771. end;
  1772. AS_END :
  1773. break; { end assembly block }
  1774. else
  1775. Begin
  1776. Message(asmr_e_syntax_error);
  1777. RecoverConsume(false);
  1778. end;
  1779. end; { end case }
  1780. until false;
  1781. { Check LocalLabelList }
  1782. LocalLabelList.CheckEmitted;
  1783. LocalLabelList.Free;
  1784. { Return the list in an asmnode }
  1785. assemble:=casmnode.create(curlist);
  1786. Message1(asmr_d_finish_reading,'intel');
  1787. end;
  1788. {*****************************************************************************
  1789. Initialize
  1790. *****************************************************************************}
  1791. const
  1792. asmmode_i386_intel_info : tasmmodeinfo =
  1793. (
  1794. id : asmmode_i386_intel;
  1795. idtxt : 'INTEL'
  1796. );
  1797. initialization
  1798. RegisterAsmMode(asmmode_i386_intel_info);
  1799. finalization
  1800. if assigned(iasmops) then
  1801. iasmops.Free;
  1802. end.
  1803. {
  1804. $Log$
  1805. Revision 1.55 2003-10-07 18:21:18 peter
  1806. * fix crash
  1807. * allow parameter subscription for register parameters
  1808. Revision 1.54 2003/10/02 21:17:38 peter
  1809. * fix operand order when a prefix opcode is supplied
  1810. Revision 1.53 2003/10/01 20:34:49 peter
  1811. * procinfo unit contains tprocinfo
  1812. * cginfo renamed to cgbase
  1813. * moved cgmessage to verbose
  1814. * fixed ppc and sparc compiles
  1815. Revision 1.52 2003/09/23 20:37:53 peter
  1816. * fix global var+offset
  1817. Revision 1.51 2003/09/23 17:56:06 peter
  1818. * locals and paras are allocated in the code generation
  1819. * tvarsym.localloc contains the location of para/local when
  1820. generating code for the current procedure
  1821. Revision 1.50 2003/09/03 15:55:01 peter
  1822. * NEWRA branch merged
  1823. Revision 1.49.2.2 2003/08/31 15:46:26 peter
  1824. * more updates for tregister
  1825. Revision 1.49.2.1 2003/08/28 18:35:08 peter
  1826. * tregister changed to cardinal
  1827. Revision 1.49 2003/06/06 14:41:59 peter
  1828. * use setsize for size specifier
  1829. Revision 1.48 2003/05/30 23:57:08 peter
  1830. * more sparc cleanup
  1831. * accumulator removed, splitted in function_return_reg (called) and
  1832. function_result_reg (caller)
  1833. Revision 1.47 2003/04/30 15:45:35 florian
  1834. * merged more x86-64/i386 code
  1835. Revision 1.46 2003/04/27 11:21:35 peter
  1836. * aktprocdef renamed to current_procdef
  1837. * procinfo renamed to current_procinfo
  1838. * procinfo will now be stored in current_module so it can be
  1839. cleaned up properly
  1840. * gen_main_procsym changed to create_main_proc and release_main_proc
  1841. to also generate a tprocinfo structure
  1842. * fixed unit implicit initfinal
  1843. Revision 1.45 2003/04/21 20:05:10 peter
  1844. * removed some ie checks
  1845. Revision 1.44 2003/03/28 19:16:57 peter
  1846. * generic constructor working for i386
  1847. * remove fixed self register
  1848. * esi added as address register for i386
  1849. Revision 1.43 2003/03/18 18:15:53 peter
  1850. * changed reg2opsize to function
  1851. Revision 1.42 2003/03/17 21:32:52 peter
  1852. * allow character constants in reference declaration
  1853. Revision 1.41 2003/02/26 22:57:44 daniel
  1854. * Changed no longer correct fillchar of reference into location_reset
  1855. Revision 1.40 2003/02/19 22:00:16 daniel
  1856. * Code generator converted to new register notation
  1857. - Horribily outdated todo.txt removed
  1858. Revision 1.39 2003/01/08 18:43:57 daniel
  1859. * Tregister changed into a record
  1860. Revision 1.38 2002/12/14 15:02:03 carl
  1861. * maxoperands -> max_operands (for portability in rautils.pas)
  1862. * fix some range-check errors with loadconst
  1863. + add ncgadd unit to m68k
  1864. * some bugfix of a_param_reg with LOC_CREFERENCE
  1865. Revision 1.37 2002/12/01 22:08:34 carl
  1866. * some small cleanup (remove some specific operators which are not supported)
  1867. Revision 1.36 2002/11/15 01:58:59 peter
  1868. * merged changes from 1.0.7 up to 04-11
  1869. - -V option for generating bug report tracing
  1870. - more tracing for option parsing
  1871. - errors for cdecl and high()
  1872. - win32 import stabs
  1873. - win32 records<=8 are returned in eax:edx (turned off by default)
  1874. - heaptrc update
  1875. - more info for temp management in .s file with EXTDEBUG
  1876. Revision 1.35 2002/09/16 19:07:00 peter
  1877. * support [eax].constant as reference
  1878. Revision 1.34 2002/09/03 16:26:28 daniel
  1879. * Make Tprocdef.defs protected
  1880. Revision 1.33 2002/08/17 09:23:47 florian
  1881. * first part of procinfo rewrite
  1882. Revision 1.32 2002/08/13 18:01:52 carl
  1883. * rename swatoperands to swapoperands
  1884. + m68k first compilable version (still needs a lot of testing):
  1885. assembler generator, system information , inline
  1886. assembler reader.
  1887. Revision 1.31 2002/08/11 14:32:31 peter
  1888. * renamed current_library to objectlibrary
  1889. Revision 1.30 2002/08/11 13:24:17 peter
  1890. * saving of asmsymbols in ppu supported
  1891. * asmsymbollist global is removed and moved into a new class
  1892. tasmlibrarydata that will hold the info of a .a file which
  1893. corresponds with a single module. Added librarydata to tmodule
  1894. to keep the library info stored for the module. In the future the
  1895. objectfiles will also be stored to the tasmlibrarydata class
  1896. * all getlabel/newasmsymbol and friends are moved to the new class
  1897. Revision 1.29 2002/07/01 18:46:34 peter
  1898. * internal linker
  1899. * reorganized aasm layer
  1900. Revision 1.28 2002/05/18 13:34:26 peter
  1901. * readded missing revisions
  1902. Revision 1.27 2002/05/16 19:46:52 carl
  1903. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1904. + try to fix temp allocation (still in ifdef)
  1905. + generic constructor calls
  1906. + start of tassembler / tmodulebase class cleanup
  1907. Revision 1.25 2002/04/20 21:37:07 carl
  1908. + generic FPC_CHECKPOINTER
  1909. + first parameter offset in stack now portable
  1910. * rename some constants
  1911. + move some cpu stuff to other units
  1912. - remove unused constents
  1913. * fix stacksize for some targets
  1914. * fix generic size problems which depend now on EXTEND_SIZE constant
  1915. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  1916. Revision 1.24 2002/04/15 19:44:22 peter
  1917. * fixed stackcheck that would be called recursively when a stack
  1918. error was found
  1919. * generic changeregsize(reg,size) for i386 register resizing
  1920. * removed some more routines from cga unit
  1921. * fixed returnvalue handling
  1922. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  1923. Revision 1.23 2002/04/15 19:12:09 carl
  1924. + target_info.size_of_pointer -> pointer_size
  1925. + some cleanup of unused types/variables
  1926. * move several constants from cpubase to their specific units
  1927. (where they are used)
  1928. + att_Reg2str -> gas_reg2str
  1929. + int_reg2str -> std_reg2str
  1930. Revision 1.22 2002/04/04 19:06:13 peter
  1931. * removed unused units
  1932. * use tlocation.size in cg.a_*loc*() routines
  1933. Revision 1.21 2002/04/02 17:11:39 peter
  1934. * tlocation,treference update
  1935. * LOC_CONSTANT added for better constant handling
  1936. * secondadd splitted in multiple routines
  1937. * location_force_reg added for loading a location to a register
  1938. of a specified size
  1939. * secondassignment parses now first the right and then the left node
  1940. (this is compatible with Kylix). This saves a lot of push/pop especially
  1941. with string operations
  1942. * adapted some routines to use the new cg methods
  1943. Revision 1.20 2002/01/24 18:25:53 peter
  1944. * implicit result variable generation for assembler routines
  1945. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1946. }